2012-01-06 14 views
6

大量のメモリを使用しているASP.NET/C#Webアプリケーションがあります。大規模なGen 0メモリの浪費、.NETの浪費?

ANTS Memory ProfilerとPerfMonはどちらも、Application_Start中にGen 0ヒープが約1GBまで急速に成長していることを示しています。私はhereを読んで、Gen 0 HeapのPerfMonカウンタが、実際にはGen 0の "予算"を表示しているのではなく、サイズ(私はすべてのメモリがプロセスのプライベートな作業セットの一部ではないという意味ですか?しかし、ANTSプロファイラでは約700 MBの "未使用メモリが.NETに割り当てられました"と表示され、がプロセスのプライベートワーキングセット(taskmgrで報告されているように)に含まれているようです。私はこの大量の未使用メモリが大きなGen 0ヒープに関連していると推測しています。

Application_Startでは何が起こっているのですか?これは、私がSqlDataReaderから約100万行を読み込んでいる途中です。これらは、後で使用するために大きなキャッシュに移入するために使用されています。このことを考えると、大量の未使用メモリに対する明らかな原因は、ラージオブジェクトヒープフラグメンテーションです。しかし、私は大規模なキャッシュオブジェクトに必要以上にあらかじめ割り当てを行っているので、これは当てはまりません。確かに、私は実際にキャッシュオブジェクトに追加するループの部分をコメントアウトしてみました。割り当てられていない未使用メモリの量に違いはありませんでした。

テストとして、ループ中にgen 0のガーベッジコレクションを頻繁に強制しましたが(これはすべての推奨事項を参照してください)、gen0ヒープのサイズが約128 MBに抑えられ、未使用の空きメモリが数MBあります。しかし、それはまた、私のCPUを最大限に活用し、Application_Startを長くしすぎました。

私の質問は以下のとおりです。

1)のGen 0ヒープの報告されたサイズがそれほど大きく成長する可能性がありますか?

2)これは問題ですか?特に、大量の未使用領域が.NETに割り当てられる可能性がありますか?

3)もしそうなら、私はそれを修正するために何をすべきですか?私がApplication_Startの間に大量のメモリを使用するプロセスを防ぐことができない場合は、少なくともアプリケーションの開始が完了したときにメモリをあきらめるようにしたいと思います。

+0

Application_Startの最後に* single * forced fullガベージコレクトを実行するとどうなりますか? –

+0

Application_Startの最後にある完全なガベージコレクションは違いはありませんでした。問題は、短命のオブジェクトが多数収集された後でも、それらが占めていたすべてのメモリがまだプロセスに割り当てられていたということでした。 –

+0

しかし、私はもはやこれが問題だとは思わない。メモリが最終的にプロセスによって解放されるか、それが起こる前にトータルメモリがいっぱいになると、ディスクにスワップすることができます。この質問は同様の懸念事項に対処しています。http:// stackoverflow。com/questions/5244980 /メモリに割り当てられたときにネットプロセスによって解放されたウィンドウに戻る –

答えて

4

Gen 0には「最も新しい、最近割り当てられたオブジェクト」が含まれており、LOHとは別個のものです。そのように聞こえるのは、(キャッシュのエントリに付随する)キャッシュされていない小さなオブジェクト(そのキャッシュエントリに関連付けられているすべてのエラッタ)がルーティングされていないことですGCがそれをまだ必要とみなしていないため、タイムリーにGCは、単にクリーンアップする必要性をまだ見ていません。マシンにはどのくらいのRAMがありますか?私はあなたがページングしていないと推測しています。

.NETは、GCが不要になったと判断した場合(たとえば、ヒープスペースが長時間使用されなかったため)、未使用のヒープのチャンクをOSに返すことができます。あなたは、これが起こるかどうかを確認するために、長期間アプリを観察しましたか?あなたがページングしていない場合、私はそれが問題だとは思わない。

+0

ありがとう、Chris。私はこのようなものがあると思っていました(ガベージコレクタが小さなオブジェクトをループの前の繰り返しからきれいにするのを待っています)が、私が読むのは、Gen 0がいっぱいになってコレクションをトリガーするときでした。明らかに、GCはそれを収集するのではなく、Gen 0のサイズを増やすことを選択できます。本当? –

+0

それは本当です。 CLRが起動時にアプリケーションの適切なヒープサイズを事前に割り当てることは不可能であるため、唯一の可能性は非常に小さく(「Hello world」の場合)、追加の領域を必要です。 –

+0

私がプロファイラを実行しているテストボックスには、十分な空きメモリがあります。本当に調査を促したのは、ライブサーバ上のアプリケーションプールが、私たちが望むよりも頻繁にメモリのしきい値やリサイクルに当たっているということです。 (このメモリ消費量の多くは後で発生しますが、アプリケーション開始時に見かけ上過度のメモリ使用量を減らそうとするのは良い場所でした)。しかし、時にはメモリ使用量が大幅に低下しています。あなたが言うように、未使用のヒープのチャンクを返すGCかもしれません。 GCがこれを行うことを決定するのを待たなければならないと思います。私はそれを促すことができないのですか? –

関連する問題