当你需要调试/调查问题时,我想指出的一个非常强大的工具是你的调试器(如果你的调试器也是windbg/cdb,那就是对了,因为这就是我要用的,这也是我在本文中将要讨论的)。
对于那些对研究内存相关问题感兴趣的人来说,无论是因为你不喜欢当前应用程序的内存使用情况,还是只是想提高,学习使用调试器都是非常宝贵的。如果您还没有开始使用windbg/cdb,我强烈建议您–我保证您不会后悔的。
我以前说过使用SoS,在V4.0中添加了更多的SoS命令,其中一些与GC相关,像!AnalyzeOOM!GCWhere 和 !FindRoots。你可以在MSDN页面上看到它们。但我想谈谈一些从阅读参考资料中看不到的技巧。
当你的程序是GC时,你想知道什么是最常见的两件事吗?

1) 为什么触发GCs
2) 为什么GCs要花这么多时间?

答案分别是:

1) GC前后堆的差异
2) 那个GC的幸存者

让我详细解释一下。每一次都有自己的分配预算,我在这里解释了这一点。这是一个我们设置的值,当超过这个值时,我们想要触发一个GC。如果我们做了一个收集,发现有很多内存存留下来,我们会把这个分配预算设置得非常大,这意味着您需要为该代分配更多的内存,这样我们才能触发GC。其基本原理是,这样我们下次进行GC时就有机会回收一些相当大的空间。否则,我们将为GC做所有这些工作,而不能找到太多的死内存。
所以在GC之前,如果你运行!dumpheap,你可以看到你有什么对象;然后在GC之后你在运行!dumpheap,你会看到其中一些对象消失了。正是这些对象触发了这个GC。为什么?因为如果我们没有任何物体消失,我们就不会做GC(因为我们不会得到死内存)。
到目前为止,CLR-GC还没有压缩LOH。因此,如果你想看看LOH,你可以确切地看到内存的哪些部分消失了。下面是gen2gc前后堆范围的示例输出。在gen2gc之前(我格式化了!dumpheap,将methodtable指针替换为可读名称的)

Address              MethodTable          Size

————————————————–

00000007f7ffe1e0 System.Byte[]
2,080,00000000007f81f9ee0 System.String100,00000000007f8212580 System.Byte[]140,000After this gen2 GCforthe same heap range:



Address MethodTable Size

————————————————–

00000007f7ffe1e0 Free
2,320,000

标签: none

添加新评论