LOH分析说GC根对象(System.Object)是内存泄漏的来源

时间:2011-05-16 06:20:20

标签: asp.net garbage-collection httphandler large-object-heap

我经常调用HttpHandler。它使用Entity Framework来完成任务。

此Web应用程序的w3p.exe使用内存缓慢增加(它有一个单独的应用程序池)。我使用ANTS memory profiler并且那里有很多空闲内存(LOH)。 ANTS表示这些是GC root个对象。我检查了我的代码,但有一些intstring无法导致LOH

我追踪了泄漏的来源,但遗憾的是它的类型System.Object具有很多null属性。还有一个LinkedList,一些HashTable和一个WeakHashTable

如何找到此对象的内容并修复LOH?如何true IsReusable返回HttpHandler

1 个答案:

答案 0 :(得分:1)

首先,你必须追踪实际发生的事情。在这种情况下,我的第一个工具总是 WinDbg。

http://www.windbg.org/ http://en.wikipedia.org/wiki/WinDbg

要将其与托管/ .NET代码一起使用,您需要使用SOS(Son of Strike)扩展名:

http://msdn.microsoft.com/en-us/library/bb190764.aspx

http://blogs.msdn.com/b/johan/archive/2007/11/13/getting-started-with-windbg-part-i.aspx

所以,一旦你将WinDbg附加到你的w3wp.exe进程中,你要做的第一件事就是弄清楚堆中的实际内容:

!dumpheap -stat

这将为您提供内存中所有当前“实时”对象的格式良好的视图,以及它们中有多少,它们占用的字节数,按对象类型分组。

现在,大对象堆(LOH) - 通常,当对象被垃圾收集时,会发生压缩,就像对硬盘进行碎片整理一样。这样可以快速有效地为新对象分配。问题是,大型物体不易于压缩 - 一切都必须四处移动才能容纳它们。因此,任何占用超过85000字节的内容都会被困在一个称为大对象堆的特殊位置。这个堆不是压缩的,所以随着时间的推移,很像硬盘驱动器,会发生碎片,在堆中留下未使用的间隙,这会导致运行时需要更多的空间等等。

那么,让我们问一下windbg告诉我们LOH中的内容:

!dumpheap -stat -min 85000

这将显示大对象堆中的实际内容 - 其中一些对象可能会向您跳出,如List或MyClass []。

重要提示:如果您在大对象堆中看到的内容故意长期存在(例如,记录器的静态实例),则可能不是真正的问题。但是,您确实希望尝试减少那里短暂/经常创建的对象的数量,以减少碎片。

所以,我推荐一份SOS探索备忘单:

http://windbg.info/doc/1-common-cmds.html

http://windbg.info/doc/2-windbg-a-z.html

有趣的命令:

!gcroot <address>   <- will show you what object is "rooting" another
!CLRStack           <- show current managed call stack
!dumpobj <address>  <- show information about object at address

但我最喜欢的是:

bp clr!SVR::gc_heap::allocate_large_object "!CLRStack; g;"

它在CLR在大对象堆上分配对象时使用的实际内部调用设置断点,当命中时,将转储完整的堆栈跟踪,然后继续。