.net应用程序中的内存泄漏+奇怪的GC行为

时间:2013-05-08 23:39:00

标签: .net memory-leaks debugdiag performance-monitor

我并不完全确定在哪里寻求帮助,所以我想我会尝试使用stackoverflow,因为它通常可以解答我所有编程相关问题的90%。

简而言之,我有一个泄露内存的开源.NET应用程序。它可能不是真正的内存泄漏,当应用程序关闭时我怀疑内存被回收,但是当它运行时它不断分配更多内存而不释放它。最终,抛出System.OutOfMemoryException

为了调试问题,我遵循了this article中建议的步骤,并生成了下图,其中红色是.NET / CLR内存“#Bytes in all Heaps”,绿色是Process“Private Bytes”使用Windows的性能监视器工具(注意绿线已经统一缩小以显示更接近红线,因为只有线条的形状对我很重要):Performance Monitor Output

我将图像作为托管内存泄漏的证据,然后使用Windows的调试诊断工具来尝试找到泄漏源(如文章中所述)。然而,我从Debug Diagnostic Tool返回的报告非常特殊。

基本上每次尝试收集我在应用程序运行时每隔5秒尝试一次的“Full UserDump”时,垃圾收集器始终的事实就被挫败了当时的垃圾收集周期,导致调试诊断工具输出错误,并阻止它收集任何有用的.NET内存相关信息。

现在我被卡住了,我知道我有一个托管内存泄漏,但我不知道如何缩小它的位置。我也很困惑垃圾收集器如何总是处于收集周期的中间,它让我想知道垃圾收集线程是否以某种方式被阻止,阻止它释放内存和/或退出垃圾收集周期。

性能监视器图中有一些部分,分配的.NET内存有点下降,所以垃圾收集器没有永久停留,但它一定是大部分时间,否则Debug Diagnostic应该是能够做一个UserDump。

几个问题:

  1. .NET应用程序中的垃圾收集器是否有可能在尝试释放某些内存时遇到困难,可能来自某些编码较差的析构函数/终结器或什么东西?

  2. 我可以使用哪种策略来继续缩小问题根源?

1 个答案:

答案 0 :(得分:4)

如果您提供 .NET Framework版本,操作系统版本,您的进程的位数和计算机上的处理器数量将会有所帮助。如果你很快就会遇到Out of memory异常,那么我会认为你正在运行32位进程,但如果你能确认的话,它仍然有用。

首先,您应该通过查找流程中的 GC时间内存计数器来检查GC是否确实是导致问题的原因。您可以在.NET CLR Memory对象下的PERFMON中监视它。如果此计数器是> 30%然后肯定你有GC问题。你粘贴的PNG并没有告诉我每秒分配多少内存,所以如果它高,那么GC就会更多。

需要注意的一点是使用最新的调试诊断工具来分析转储,看看是否有不同之处。 DebugDiag 1.2中存在一个问题,它可能导致错误地报告“垃圾收集的中间”消息,因此您要确保GC在转储时是否真正运行。您可以从{下载最新版本{3}}并使用该工具分析相同的转储文件,看看是否报告了不同的内容。还要在报告中搜索 GarbageCollectionGeneration 字符串,这将显示负责调用GC的线程。查看该线程的堆栈,您可以识别该线程正在执行哪些操作最终调用GC。这可能有所帮助,也可能没有帮助。

回答您的其他问题: -

1)如果任何线程已禁用PRE-EMPTIVE GC,GC可能会卡住。您可以阅读文章http://www.microsoft.com/en-us/download/details.aspx?id=40336以了解有关PRE-EMPTIVE GC以及如何找出已禁用先发制人GC的线程。

2)我会在WinDBG中打开转储,并查看上面博客中提到的方法,看看我是否到达某个地方。如果框架是.net framework 4.0或更高版本,您还可以使用PERFVIEW工具收集跟踪,并提供有关GC发生原因的详细信息。查看PERFVIEW的视频,以便在http://blogs.msdn.com/b/tess/archive/2008/02/11/hang-caused-by-gc-xml-deadlock.aspx

处解决GC问题

此外,如果此EXE正在进行后台处理,您可能需要启用GC的服务器模式并查看是否有帮助。阅读文章http://channel9.msdn.com/Series/PerfView-Tutorial/PerfView-Tutorial-9-NET-Memory-Investigation-Basics-of-GC-Heap-Snapshots以获取更多相关信息。

希望这会有所帮助!!!