0

膨大な量の地図データを処理する WinForm アプリケーションがあります。操作を高速化するために、頻繁にアクセスされるマップ データを格納するキャッシュ (単純なハッシュ テーブル) があります。キャッシュのサイズを制限している間、タスク マネージャーは増え続けるメモリ消費を示し、最後に OutOfMemoryException を取得します。 奇妙なことに、メモリ プロファイラーと GC.GetTotalMemory の両方と、独自のオブジェクト サイズの計算は同じことを示しています。つまり、キャッシュは制限セットよりも多くのメモリを使用することはありません。キャッシュを無効にすると、システムは正常に動作します。マップ データの処理中に数秒間ピークに達しますが、その後は通常に戻ります。

メモリ プロファイラーは、使用済みスペース (緑色で示されます) がキャッシュ サイズに正確に対応していることを示していますが、予約済みメモリの大部分は使用されていません
プロファイリング セッション中に、4 つのメモリ スナップショットを取得しました。

  • メモリ スナップショット 1: キャッシュあり (最大キャッシュ サイズ 300MB)
  • メモリ スナップショット 2: キャッシュ オフ
  • メモリ スナップショット 3: 再度キャッシュを有効にする (最大キャッシュ サイズ 300MB)
  • メモリ スナップショット 4: 再度キャッシュをオフにする

以下の色分けを見てください。これらの巨大な未使用スペース (青) が取り戻されないのはなぜですか? GC.Collect を呼び出しても違いはありません

メモリ プロファイリング セッション、キャッシュのオンとオフの切り替え

4

1 に答える 1

0

Hans がコメントで指摘したように、根本的な問題はメモリの断片化でした。キャッシュされたオブジェクト (かなり大きなもの) の作成中に、多くの中サイズの一時オブジェクトがあり、大きな永続オブジェクトの間にギャップが生じました。再利用によって一時オブジェクトの量を減らすとすぐに、断片化は急激に減少しました。

グラフからわかるように、使用済みスペースと未使用スペースの比率は 1:2 でした。変更後の比率は 8:1 です。

于 2013-06-14T14:20:27.130 に答える