.net应用程序对象升级为第2代

Vin*_*dey 3 .net c# windbg

我一直试图在我的应用程序中修复内存泄漏.几个月前,我注意到在我的应用程序中,超过95%的对象被提升为Gen2; 我有一些非常基本的问题,我在书中找不到.我希望你们能帮助我:

  1. 有这么多Gen2对象是坏消息吗?在我拍摄的每个快照中,我在WinDbg中获得77,000个Gen2对象,100个Gen1对象和10个Gen0对象.
  2. 我怎样才能找到这么多对象被提升的原因?有一个好工具吗?我一直在使用WinDbg/SOS而且运气不好

先感谢您.

小智 13

有这么多Gen2对象是坏消息吗?

这不是坏消息.这可能意味着GC.Collect刚刚运行,或者它经常运行,并且你有足够的空闲内存 - 因此Gen2中的对象不会被收集.以下是另一个StackOverflow问题的一些很好的解释, 垃圾收集即使在需要时也没有发生:

启动垃圾收集时,GC确定需要收集哪些代(0,0 + 1或全部).每一代都有一个由GC确定的大小(它可以随着应用程序的运行而改变).如果只有第0代将超过其预算,那么这是唯一将收集垃圾的一代.如果在第0代中存活的对象将导致第1代超过其预算,那么第1代也将被收集,其幸存的对象将被提升为第2代(这是Microsoft实现中的最高代).如果超过第2代的预算,则将收集垃圾,但是不能将对象提升到更高的一代,因为不存在.

因此,这里有重要信息,以最常见的方式启动GC,只有在第0代和第1代都满时才会收集第2代.此外,您需要知道超过85,000个字节的对象不会存储在具有第0代,第1代和第2代的普通GC堆中.它实际上存储在所谓的大对象堆(LOH)中.LOH中的内存仅在FULL集合期间释放(即,在收集第2代时); 从来没有只收集过0或1代.

对于你的第二个问题:

我怎样才能找到这么多对象被提升的原因?有一个好工具吗?我一直在使用WinDbg/SOS而且运气不好

Windbg和SOS很好:)在这种情况下我建议添加psscor2(或psscor4,如果使用.NET 4.0)你需要使用psscor轻松转储特定代的对象.

以下是下载psscor2psscor4 dll的官方链接.将适当版本的版本放入安装Windbg的文件夹中.x86版本的dll到x86文件夹(C:\ Program Files(x86)\ Debugging Tools for Windows),x64版本的dll到x64文件夹(C:\ Program Files\Debugging Tools for Windows(x64)).

然后你就可以运行下一个命令:

    !dumpheap -gen 2
Run Code Online (Sandbox Code Playgroud)

当psscor这样做时,SOS没有简单的命令来转储特定代的对象.

使用此命令,您可以创建类似的结构

.foreach (obj { !dumpheap -gen 2 -short }) { !do ${obj} }
Run Code Online (Sandbox Code Playgroud)

要么

.foreach (obj { !dumpheap -gen 2 -type ExactTypeName -short }) { !gcroot ${obj} }
Run Code Online (Sandbox Code Playgroud)

找出第2代中对象的主要类型,以及哪些方法引用它们.

正如你所说,你的主要想法是找到内存泄漏,你应该使用更通用的方法,而不仅仅分析生成.以下是我分析高内存使用问题的帖子:

管理记忆:

http://kate-butenko.blogspot.com/2012/06/investigating-memory-issues-high-memory.html

非托管内存:

http://kate-butenko.blogspot.com/2012/07/investigating-issues-with-unmanaged.html

http://www.codeproject.com/Articles/31382/Memory-Leak-Detection-Using-Windbg

如果您仍然坚持一些步骤,请留下您的问题.