Daily Grind

システム開発関連の忘備録です

.NET上アプリケーションのメモリ解析

http://moated.wordpress.com/2011/07/30/windows-net%E4%B8%...

.NET用のアプリケーションのパフォーマンスを改善する必要があって調べもの。
メモリ関連については、以下の記事が参考になった。
これ以外の記事もあって、VADumpやCLR profilerが紹介されていた。

Investigating Memory Issues
Claudio Caldato and Maoni Stephens
http://msdn.microsoft.com/en-us/magazine/cc163528.aspx
windbgやメモリダンプを使う方法が前半で少しだけ出てくる。

perfmonを使う方法のまとめ。

% Time in GC。これが50%を超えたままだと、managed heapがどうなっているのか見た方がいい。10%を超えていないならまず心配いらない。
Allocated Bytes/secを見る。メモリのallocation rate。正確ではないのでallocateしていても0になることがある。表示と数値の更新速度が違うからだ。低い数値は0になると考えておく。
85000バイト以上の大きいオブジェクトを作っている可能性があれば、Large Object Heapサイズを見る。
オブジェクトの生存期間が短ければGen 0のガーベジコレクションで回収される。

# Gen 0 Collection、# Gen 1 Collection、# Gen 2 Collectionは、プロセス開始からの各世代のGCの回数集計値。Gen 0, Gen 1は短時間で終了する。Gen2 は全部見るのでここで回収されるとコストが高い。
Gen 1 の回数とGen 2の回数のざっくりとした指標は10対1。

Allocation rateが高くないのにGCが多い(% Time in GCが大きい)ときは、次の世代に生き残るオブジェクトが大きいことがある。Promoted Memory from Gen 0とPromoted Memory from Gen 1でそれがわかる。特にGen 1からpromoteされてGen 2に上がり、そこで回収されるとパフォーマンスに影響がある。この状態はmidlife crisisと呼ばれるらしい。

promoteされるサイズが大きいとheapも大きい。これはGen 1 heap size と Gen 2 heap sizeで見る。Gen 0 heap sizeは次のGen 0 GCが開始される条件となるサイズ(ここまでallocできる)であり溜まっているサイズではない。
Promoted Finalization-Memory from Gen 0 はfinalizationが必要なオブジェクトの量。finalizeするまで再利用できないのでサイズが増加する要因になる。

# Total committed Bytes はGCヒープ上でcommitされたメモリ、 # Total reserved Bytesは同じくreserveされたメモリ。ヒープを広げて次のセグメントを確保すると、reserveされ、実際に使用するときまでcommitはされていない。

# Induced GC は、GCを要求した回数。これが多いのはバグの可能性もある。GCヒープを削減するためにinduceするよりはヒープを増やさないような方策を考えることで解決するべき。
.NETのGCとは別だが、memory カテゴリーのAvailable Bytesで使用可能な物理メモリがわかる。% Committed Bytesは、commit limitとcommited chargeの比率。90%を超えるとcommit エラーが発生するかもしれない。
Process カテゴリーのPrivate Bytes は、プロセスのprivate(共有不可能な)サイズ。大きいprivateサイズには注意が必要。これが増加していくときはメモリリークの可能性がある。
記事の後半はwindbgを使った解析について説明している。