3

我有一个HttpHandler经常被调用的。它Entity Framework用来完成它的任务。

此 Web 应用程序的已用内存增长缓慢w3p.exe(它有一个单独的应用程序池)。我用过ANTS memory profiler,那里有很多可用内存(LOH)。ANTS说这些是GC root对象。int我检查了我的代码,有一些string不能导致LOH

我追踪了泄漏的来源,但不幸的是它是System.Object具有很多null属性的类型。还有 a LinkedList、 some HashTables 和 a WeakHashTable

我怎样才能找到这个对象并修复LOH?回来true了怎么IsReusableHttpHandler

4

1 回答 1

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-az.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 在大对象堆上分配对象时使用的实际内部调用上设置断点,当命中该对象时,将转储完整的堆栈跟踪,然后继续。

于 2012-10-02T06:48:54.793 回答