我有一个C#应用程序,它的内存使用超时增加。我进行了定期的用户模式转储,在加载sos之后,运行!EEHeap -gc来监控托管堆的大小。在windbg/sos中,我看到它从大约14MB开始增长到160MB,然后缩小到15MB,但应用程序的"Private Bytes“从未显著减少。我已经确定了导致"Private Bytes“增加的活动,因此我可以控制内存增长的时间。
我尝试运行Vmmap.exe,注意到它报告了一个大约360MB的托管堆,进行了一个快速转储,然后使用windbg/sos/eeheap -gc,我只看到了15MB。
为什么我看到了如此不同的值?托管堆真的是vmmap.exe所报告的吗?
如何在windbg中检查托管堆的这一区域?
发布于 2014-05-01 06:46:30
您不能在使用WinDbg进入.NET应用程序的同时运行VMMap。这将导致VMMap挂起。您也不能以相反的方向执行此操作:首先启动VMMap,然后进入WinDbg,然后刷新VMMap中的值。
因此,VMMap显示的值可能永远不相等,因为这些数字来自不同的时间点。不同的时间点也可能意味着垃圾收集器已经运行。如果应用程序的变化不是很大,则这些值应该接近。
在我的测试中,VMMap中的托管堆的提交部分是!eeheap -gc和!eeheap -loader的总和,这听起来很合理。
给定!eeheap -gc的输出,我们得到的GC堆开始于第2代(11aa0000),大小只有3.6MB。
Number of GC Heaps: 1
generation 0 starts at 0x0000000011d110f8
generation 1 starts at 0x0000000011cd1130
generation 2 starts at 0x0000000011aa1000
...
GC Heap Size 0x374a00(3623424)!address给出了详细信息:
...
+ 0`11aa0000 0`11ef2000 0`00452000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE <unknown>
0`11ef2000 0`21aa0000 0`0fbae000 MEM_PRIVATE MEM_RESERVE <unknown>
0`21aa0000 0`21ac2000 0`00022000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE <unknown>
0`21ac2000 0`29aa0000 0`07fde000 MEM_PRIVATE MEM_RESERVE <unknown>
+ 0`29aa0000 0`6ca20000 0`42f80000 MEM_FREE PAGE_NOACCESS Free
...虽然没有记录,但我相信一个新的细分市场是从11aa0000开始的,由+标志表示。GC段在29aa0000处结束,这也是下一段的起点。交叉检查:在最后一列中,.NET内存应报告为<unknown> - ok。
总GC大小(保留+提交)为
?29aa0000-11aa0000
Evaluate expression: 402653184 = 00000000`18000000这是402MB或393.216 kB,在我的例子中,这非常接近VMMap报告的395.648 kB。
如果您有更多的GC堆,则整个过程需要更多的工作。因此,我通常选择捷径,如果您知道除了调用VirtualAlloc()的.NET之外没有其他东西,那么这是可以的。键入!address -summary,然后查看第一个<unknown>条目:
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 144 7ff`d8a09000 ( 7.999 Tb) 99.99%
<unknown> 180 0`1a718000 ( 423.094 Mb) 67.17% 0.01%
...发布于 2014-05-02 03:07:45
非常感谢你的详细回答。非常感谢。
我很清楚windbg和VMmap对程序的访问/控制。由于我可以通过外部操作导致泄漏,因此我非常确定,因为我停止了活动,所以两个样本之间的内存不会增加太多。
我一直依赖于!eeheap -gc的最后一行输出:
GC堆大小:大小: 0xed7458 (15561816)字节。
我认为这个数字必须是正在使用的托管堆的数量(其中包含未释放的对象)。我对每个SOH和LOH的"!eeheap -gc“报告的所有"size”字节求和,结果与上面的值匹配。
我运行了VMmap,拍了一张快照,然后退出了VMmap。然后我使用windbg附加到进程中。您使用!address的技巧非常有启发性。我使用的是一个12处理器的服务器系统,所以每个处理器都有SOH和LOH,即加起来有12个。首先,"!eeheap -gc“的输出包含所有堆的段。我将它们都输入到"!address“中,并对它们的大小求和(加上!eeheap -loader报告的大小)。结果是335,108K,这是我期望在过去的时间内看到的变化(在600K内)。VMmap托管堆似乎是提交给托管堆使用的所有内存段的总量(我没有检查保留数量)。所以现在我明白了为什么"!eeheap -gc“报告的总数比VMmap显示的要少得多。谢谢!
https://stackoverflow.com/questions/23391200
复制相似问题