我有一个C#应用程序,其内存使用时间增加.我定期进行用户模式转储,加载sos后,运行!EEHeap -gc来监控托管堆大小.在windbg/sos中我看到它开始~14MB并且长到160MB,然后缩减到15MB,但应用程序"Private Bytes"从未显着下降.我已经确定了可以控制"私有字节"增加的活动,因此我可以控制内存增长何时发生.
我尝试运行Vmmap.exe并注意到它报告了~360MB的托管堆,快速转储并使用windbg/sos/eeheap -gc我只看到15MB.
为什么我会看到这样不同的价值观?托管堆真的是vmmap.exe报告的吗?
如何在windbg中检查托管堆的这个区域?
您无法使用WinDbg进入.NET应用程序,然后同时运行VMMap.这将导致挂起的VMMap.您也可以不以相反的方向执行:首先启动VMMap,然后进入WinDbg,然后刷新VMMap中的值.
因此,VMMap显示的值可能永远不会相等,因为数字来自不同的时间点.不同的时间点也可能意味着垃圾收集器已经运行.如果应用程序变化不大,则值应该接近.
在我的测试中的VMMap托管堆的承诺部分的总和!eeheap -gc,并!eeheap -loader,这听起来很有道理.
给定输出!eeheap -gc,我们在第2代(11aa0000)获得GC堆的开始,并且只有3.6 MB的大小.
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)
Run Code Online (Sandbox Code Playgroud)
!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
...
Run Code Online (Sandbox Code Playgroud)
虽然没有记录,但我相信一个新的部分从11aa0000开始,由+符号表示.GC段结束于29aa0000,这也是下一段的起点.交叉检查:应该<unknown>在最后一列中报告.NET内存- 好的.
总GC大小(保留+已提交)是
?29aa0000-11aa0000
Evaluate expression: 402653184 = 00000000`18000000
Run Code Online (Sandbox Code Playgroud)
这是402 MB或393.216 kB,在我的情况下非常接近VMMap报告的395.648 kB.
如果你有更多的GC堆,整个过程需要更多的努力.因此,我通常采用快捷方式,如果您知道除了.NET之外没有其他任何调用VirtualAlloc()的东西,那就没问题了.键入!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%
...
Run Code Online (Sandbox Code Playgroud)