首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么windbg> !EEHeap -gc显示的托管堆比VMMAP.exe小得多?

为什么windbg> !EEHeap -gc显示的托管堆比VMMAP.exe小得多?
EN

Stack Overflow用户
提问于 2014-04-30 22:44:36
回答 2查看 3K关注 0票数 2

我有一个C#应用程序,它的内存使用超时增加。我进行了定期的用户模式转储,在加载sos之后,运行!EEHeap -gc来监控托管堆的大小。在windbg/sos中,我看到它从大约14MB开始增长到160MB,然后缩小到15MB,但应用程序的"Private Bytes“从未显著减少。我已经确定了导致"Private Bytes“增加的活动,因此我可以控制内存增长的时间。

我尝试运行Vmmap.exe,注意到它报告了一个大约360MB的托管堆,进行了一个快速转储,然后使用windbg/sos/eeheap -gc,我只看到了15MB。

为什么我看到了如此不同的值?托管堆真的是vmmap.exe所报告的吗?

如何在windbg中检查托管堆的这一区域?

EN

回答 2

Stack Overflow用户

发布于 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。

代码语言:javascript
复制
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给出了详细信息:

代码语言:javascript
复制
...
+        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大小(保留+提交)为

代码语言:javascript
复制
?29aa0000-11aa0000
Evaluate expression: 402653184 = 00000000`18000000

这是402MB或393.216 kB,在我的例子中,这非常接近VMMap报告的395.648 kB。

如果您有更多的GC堆,则整个过程需要更多的工作。因此,我通常选择捷径,如果您知道除了调用VirtualAlloc()的.NET之外没有其他东西,那么这是可以的。键入!address -summary,然后查看第一个<unknown>条目:

代码语言:javascript
复制
--- 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%
...
票数 6
EN

Stack Overflow用户

发布于 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显示的要少得多。谢谢!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23391200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档