如何在没有堆栈跟踪的情况下调试OutOfMemoryException?

时间:2019-10-23 06:50:05

标签: c# out-of-memory

当我在Linux服务器上运行.NET Core应用程序时,出现OutOfMemoryException。我完全不知道如何调试它,因为没有提供堆栈跟踪。唯一的输出是:“未处理的异常:OutOfMemoryException。”

当前抛出此异常时,还有足够的空间。使用了200 GB的RAM和300GB的可用空间,因此我认为内存应该没有任何问题。

发生这种情况的时刻是我尝试将一个对象序列化为protobuf。最终文件应约为1GB。我以前从未遇到过这个问题,模型序列化也很好。

我将非常感谢您的任何见解。我真的需要使它工作:(我已经尝试在序列化之前调用此权限,因为我认为问题在于碎片。经过10个小时的计算,我意识到情况并非如此。

_logger.LogDebug("LOH compaction start");
GCSettings.LargeObjectHeapCompactionMode = 
GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
_logger.LogDebug("LOH compaction end");

抛出异常时我正在执行的代码是:

        public static void Serialize<T>(this ProtobufSerializer protobufSerializer, string filePath, T serializationObject)
        {
            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                protobufSerializer.Serialize(fileStream, serializationObject);
            }
        }

2 个答案:

答案 0 :(得分:2)

您需要一种非常系统的方法来识别和解决OOM。

  1. 不要以为如果您有很多可用的RAM,那么就全部用于您的应用程序了。
  2. OOM会掩饰自己,因此臭名昭著,您可能会看到Stack Trace指向其他地方,而问题实际上可能出在其他地方,在某种意义上,其他一些代码正在泄漏/消耗大量内存,并将内存使用率摆在了边缘而试图在其他地方保护有限内存的合法代码会将其推向OOM。
  3. 使用一些探查器,并确定内存正在增加/泄漏的区域。 (看起来您已经将其标识为序列化大数据的代码。)
  4. 然后在那些区域上工作,并尽量减少内存使用。

答案 1 :(得分:0)

仅当系统位大小未达到所使用对象的大小级别时,才会引发OutOfMemory异常。

OutOfMemoryException异常有两个主要原因:-

1。您正在尝试扩展StringBuilder对象,使其超出其StringBuilder.MaxCapacity属性定义的长度。

2。公共语言运行库无法分配足够的连续内存来成功执行操作