簡體   English   中英

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

[英]Why does windbg> !EEHeap -gc show a much smaller managed heap than VMMAP.exe?

我有一個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)

!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> -確定。

GC的總大小(保留+提交)為

?29aa0000-11aa0000
Evaluate expression: 402653184 = 00000000`18000000

這是402 MB或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%
...

非常感謝您提供詳細的答案。 非常感激。

我很清楚該程序的windbg vs VMmap訪問/控制。 由於我可以通過外部操作引起泄漏,因此我非常確定,由於我停止了該活動,因此樣本之間的內存不會增加太多。

我一直依靠!eeheap -gc的最后一行輸出:

GC堆大小:大小:0xed7458(15561816)字節。

我認為這個數字必須是正在使用的托管堆的數量(其中包含未釋放的對象)。 我對每個SOH和LOH匯總了“!eeheap -gc”報告的所有“大小”字節,它與上述值匹配。

我運行了VMmap,快照並退出了VMmap。 然后,我使用windbg附加了該過程。 您使用!address的技術很有啟發性。 我使用的是12處理器服務器系統,因此每個處理器都有SOH和LOH,即12求和。 帶頭,“!eeheap -gc”的輸出包含所有堆的段。 我將它們全部饋入“!address”並求和它們的大小(加上!eeheap -loader報告的大小)。 結果是335,108K,在我希望經過的時間內看到的變化范圍內(600K以內)。 VMmap托管堆似乎是承諾供托管堆使用的所有內存段的總數(我沒有檢查預留編號)。 所以現在我明白了為什么“!eeheap -gc”報告的總數比VMmap顯示的少得多。 謝謝!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM