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

发布于 2024-11-07 02:55:51 字数 542 浏览 9 评论 0原文

我有一个经常被调用的HttpHandler。它使用实体框架来完成其任务。

此 Web 应用程序的 w3p.exe 使用的内存缓慢增加(它有一个单独的应用程序池)。我使用了 ANTS 内存分析器,那里有很多可用内存(LOH)。 ANTS 表示这些是 GC root 对象。我检查了我的代码,有一些 intstring 不能导致 LOH

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

我怎样才能找到这个对象是什么并修复LOH?对于 HttpHandlerIsReusable 返回 true 怎么样?

I have a HttpHandler which is called frequently. It uses Entity Framework to accomplish its task.

There's slow increasing in used memory by the w3p.exe of this web application (it has a separate application pool). I used ANTS memory profiler and there are a lot of free memory there (LOH). ANTS says these are GC root objects. I checked my code and there are a few int and string which cannot result in LOH!

I traced the source of leak but unfortunately it's of type System.Object with a lot of null properties. Also there is a LinkedList, some HashTables and a WeakHashTable.

How can I find what is this object and fix LOH? What about returning true for IsReusable of HttpHandler?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

老旧海报 2024-11-14 02:55:51

首先,您必须追踪到底发生了什么。在这种情况下,我的第一个工具总是 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 在大对象堆上分配对象时使用的实际内部调用上设置断点,当命中该对象时,将转储该对象输出完整的堆栈跟踪,然后继续。

First things first, you've gotta track down what is actually happening. In situations like this, my first tool is always WinDbg.

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

To use it with managed/.NET code, you'll need to use SOS (Son of Strike) extension:

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

So, once you've attached WinDbg to your w3wp.exe process, the first thing you'll want to do is figure out what is actually in your heaps:

!dumpheap -stat

This will give you a nicely formatted view of all the currently "live" objects in memory, along with how many of them there are, how many bytes they are taking up, grouped by object type.

Now, the Large Object Heap (LOH) - so normally, as objects are garbage collected, a compaction occurs, kind of like defragmenting a hard drive. This keeps allocations for new objects fast and efficient. Problem is, large objects are not easy to compact - everything has to move around to accomodate them. So, anything that takes up more than 85000 bytes is stuck in a special place called the Large Object Heap. This heap is NOT compacted, so over time, much like a hard drive, fragmentation occurs, leaving unused gaps in the heap, which leads to the runtime needing more space, etc, etc.

So, let's ask windbg to tell us what is in the LOH:

!dumpheap -stat -min 85000

This will show you what is actually in the Large Object Heap - some of these objects may jump right out at you, like a List or a MyClass[].

IMPORTANT: If the things you see in the Large Object Heap are intentionally long-lived (like a static instance of a logger, for example), it's probably not really a problem. You do want to try and keep down the number of short-lived/often created objects in there, however, to reduce fragmentation.

So, I recommend a cheat sheet for SOS exploration:

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

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

Fun commands:

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

But my all-time favorite is:

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

Which sets a breakpoint on the actual internal call the CLR uses when allocating an object on the large object heap that, when hit, will dump out a full stack trace, then continue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文