6

物語:

.NET2.0アプリケーションで管理されていないメモリリークに直面しています。開始後のプロセスは約150MBを消費します(そのほとんどは.NETで管理され、オブジェクトの状態などです)。約12時間の実行後、プロセスは最大800MBを消費し、次の12時間後、プロセスには約1.8GBのRAMが搭載されます。JetBrains .NET Memory Profiler、ANTS、.NET Memory Profiler(およびおそらく市場で入手可能な2つの次のmemプロファイル)を試しましたが、後で検出すると、プロセスが管理されていない非管理領域で大量のメモリを消費するため、これは役に立ちません。これを検出するために、カウンター付きのPerfモニターを使用しました:Private Bytes(Process)および#Bytes in All Heaps(.NET CLR Memory)ここで、Private Bytesはプロセスによって割り当てられたすべてのメモリの約90%を消費します。これが、アンマネージデバッグに切り替える理由です。

DebugDiag:プロセスでdebugdiagを実行し、完全なダンプを取得します。スナップショットは次のとおりです。

  • mscorwks.dll(既知のWindowsメモリマネージャー)は、781,73Mバイト相当の未処理の割り当てを担当します。これらの割り当ては、次のモジュールおよび機能から発生したようです。

  • ntdll.dll(既知のWindowsメモリマネージャー)は、98,24Mバイト相当の未処理の割り当てを担当します。これらの割り当ては、次のモジュールおよび機能から発生したようです。

割り当て数による上位4つの機能

  • mscorwks!EEHeapAlloc +15b-80957割り当て
  • mscorwks!CLRMapViewOfFileEx +4a-4171割り当て

割り当てサイズ別の上位4つの機能

  • mscorwks!EEVirtualAlloc +15b-117,50Mバイト
  • mscorwks!EEHeapAlloc +15b-15,03Mバイト

興味深いログが見つかりました:

機能詳細

Function mscorwks!EEVirtualAlloc+15b

  • 割り当てタイプ仮想メモリの割り当て
  • 割り当てカウント1471割り当て
  • 割り当てサイズ117,50Mバイト
  • リーク確率73%

Function mscorwks!EEHeapAlloc+15b

  • 割り当てタイプヒープ割り当て
  • 割り当てカウント80957割り当て
  • 割り当てサイズ15,03Mバイト
  • リーク確率72%

Function mscorwks!CExecutionEngine::CheckThreadState+fe

  • 割り当てタイプヒープ割り当て
  • ヒープハンドル0x00000000`00000000
  • 割り当てカウント2割り当て
  • 割り当てサイズ304バイト
  • リーク確率98%

Function mscorwks!CLRMapViewOfFileEx+4a

  • 割り当てタイプ仮想メモリの割り当て
  • 割り当てカウント4171割り当て
  • 割り当てサイズ0バイト
  • リーク確率73%

誰かに私を正しい方向に押してもらいたいのですが、どうすればこのダンプからのメモリリークを見つけることができますか?ダンプをwindbgにロードして、windbgコマンドの標準セットを実行することはできますが、リークを分離できる適切なコマンドがどれであるかわかりません。

誰かがこれを手伝いたいなら、私は完全なダンプを提供することができます。

4

3 に答える 3

3

ダンプ ファイルを見ると、マネージ ヒープ上だけではなく、マネージ リークのようです。ダンプは、マネージ ヒープが非常に小さいことを示していますが、ローダー ヒープは 1 GB です。このプロセスには、35000 を超える動的アセンブリがあります。それらのいくつかを調べたところ、シリアライゼーション (XML およびバイナリ) のようです。このブログ投稿をご覧ください。同様の問題について説明しています。

于 2012-10-05T16:56:25.240 に答える
1

.NET と Silverlight のメモリ リークをデバッグする私のお気に入りの方法は、SOS 拡張機能を使用することです。簡単なチュートリアルについては、http: //blogs.msdn.com/b/ricom/archive/2004/12/10/279612.aspxを参照してください。

私が一般的にしていることは次のとおりです。

  1. !DumpHeap -stat を使用して、メモリ内に存在するオブジェクトのリストを取得します。これは通常、問題の原因を示します (たとえば、一度だけ使用して廃棄する必要がある小さなオブジェクトが 100 万個ある場合)。
  2. 原因となっているオブジェクトの種類がわかったら、!DumpHeap を使用してそのようなオブジェクトのリストをダンプし、それらのいくつかのルート (!GCRoot) をランダムに取得します。これは通常、リークのあるオブジェクトへの参照を予期せず保持しているオブジェクトを示します。

これは、マネージ メモリ リーク (参照が予期しない場所に保持されている) に対処していることを前提としています。アンマネージ メモリ リークに対処している場合はあまり役に立ちませんが、アプリケーションが多くの手動アンマネージ メモリ管理 (P/Invoke のオブジェクト マーシャリングなど) を行わない限り、その可能性ははるかに低くなります。

于 2012-10-04T12:11:29.290 に答える
0

弱い参照を使用すると、メモリ使用量が削減される場合がありますhttp://en.wikipedia.org/wiki/Weak_reference ..これは非常に一般的ですが、一度はほとんど数GBの節約になりました

于 2012-10-04T12:00:18.670 に答える