我一直试图在我的应用程序中修复内存泄漏很长一段时间。几个月前,我注意到在我的应用程序中,超过95%的对象被提升为Gen2;我有一些非常基本的问题,我在书中找不到。我希望你们能帮助我:
提前谢谢。
答案 0 :(得分:13)
有这么多Gen2对象是坏消息吗?
这不是坏消息。这可能意味着GC.Collect刚刚运行,或者它经常运行,并且你有足够的空闲内存 - 因此Gen2中的对象不会被收集。以下是另一个StackOverflow问题的一些很好的解释, Garbage Collection not happening even when needed:
启动垃圾收集时,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轻松转储特定代的对象。
以下是下载psscor2和psscor4 dll的官方链接。将适当版本的版本放入安装Windbg的文件夹中。 dll的86版本x86文件夹(C:\程序文件(x86)\ Windows调试工具),动态链接库的64位版本的x64文件夹(C:\ Program Files文件\ Windows调试工具(64))。
然后你就可以运行下一个命令:
!dumpheap -gen 2
当psscor这样做时,SOS没有简单的命令来转储特定代的对象。
使用此命令,您可以创建
之类的结构.foreach (obj { !dumpheap -gen 2 -short }) { !do ${obj} }
或
.foreach (obj { !dumpheap -gen 2 -type ExactTypeName -short }) { !gcroot ${obj} }
找出gen 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
如果你仍然坚持一步,请留下你的问题。