web-dev-qa-db-ja.com

.NETでメモリが断片化する原因

Red Gates ANTSメモリプロファイラーを使用してメモリリークをデバッグしています。それは私に警告し続けます:

メモリの断片化により、.NETが予約する空きメモリが多すぎる可能性があります。

または

メモリの断片化は、割り当て可能な最大のオブジェクトのサイズに影響を与えています

私はOCDを持っているので、この問題は解決する必要があります。

メモリの断片化を回避するのに役立つ標準のコーディング方法は何ですか。いくつかの.NETメソッドを使用して最適化できますか?それも役立つでしょうか?

49
Matt

ご存知のように、私はここのメモリプロファイラーを多少疑っています。 .NETのメモリ管理システムは、実際にメモリを移動してヒープを最適化しようとします(そのため、外部DLLと共有するためにメモリを固定する必要があります)。

長期間にわたって大量のメモリを割り当てると、断片化がさらに発生しやすくなります。小さい一時的な(短い)メモリ要求が.NETで断片化を引き起こす可能性は低いですが。

ここでも、検討する価値があります。 .NETの現在のGCでは、時間内に割り当てられたメモリは、通常、空間内で互いに近接して配置されます。これは断片化の反対です。つまり、アクセスする方法でメモリを割り当てる必要があります。

それはマネージコードのみですか、それともP/Invoke、アンマネージメモリ(Marshal.AllocHGlobal)などのものが含まれますか、またはGCHandle.Alloc(obj、GCHandleType.Pinned)などのものが含まれますか?

9
John Leidegren

GCヒープは、大きなオブジェクトの割り当てを異なる方法で処理します。それらは圧縮されませんが、代わりに隣接する空きブロックが結合されます(従来のアンマネージメモリストアのように)。

詳細はこちら: http://msdn.Microsoft.com/en-us/magazine/cc534993.aspx

したがって、非常に大きなオブジェクトを使用する場合の最良の戦略は、オブジェクトを一度割り当ててから、それを保持して再利用することです。

10

.NET Framework 4.5.1には、ガベージコレクション中にラージオブジェクトヒープ(LOH)を明示的に圧縮する機能があります。

GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();

詳細は GCSettings.LargeObjectHeapCompactionMode を参照してください

7
Andre Abrantes