2

時間の経過とともにメモリ使用量が増加する C# アプリケーションがあります。定期的にユーザー モード ダンプを取得し、sos を読み込んだ後、!EEHeap -gc を実行してマネージド ヒープ サイズを監視しました。windbg/sos では、14MB まで開始して 160MB まで成長し、その後 15MB まで縮小するのを見てきましたが、アプリケーションの「プライベート バイト」が大幅に減少することはありません。「プライベート バイト」の増加の原因となっているアクティビティを特定したので、メモリの増加がいつ発生するかを制御できます。

Vmmap.exe を実行してみましたが、約 360 MB のマネージド ヒープがレポートされ、クイック ダンプが取得され、windbg/sos/eeheap -gc を使用すると 15 MB しか表示されないことがわかりました。

なぜこのように異なる値が表示されるのでしょうか? マネージ ヒープは本当に vmmap.exe が報告するものですか?

windbg でマネージド ヒープのこの領域を調べるにはどうすればよいですか?

4

2 に答える 2

6

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 ヒープがある場合、プロセス全体でより多くの労力が必要になります。したがって、私は通常、.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%
...
于 2014-04-30T22:46:29.987 に答える
0

詳細な回答をありがとうございました。とても有難い。

プログラムのwindbgと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が示すものよりもはるかに少ないです。ありがとう!

于 2014-05-01T19:07:45.283 に答える