16

大量のデータをチャンクで転送するC#4.0アプリケーション(単一のプロデューサー/単一のコンシューマー)があります。新しいメモリ割り当てはありませんが、しばらくするとメモリが不足します。

Redgateメモリプロファイラーを使用してメモリのプロファイルを作成しましたが、そこには多くの空きメモリがあります。断片化のため、空きメモリを使用できないと表示されます。

バッファとしてブロッキングコレクションを使用し、メンバーとしてバイト配列を使用します。

BlockingCollection<byte[]> segments = new BlockingCollection<byte[]>(8);
// producer:
segments.Add(buffer);
// consumer:
byte[] buffer = _segments.Take();

管理されたメモリの断片化を回避するにはどうすればよいですか?

4

3 に答える 3

10

おそらく、ラージオブジェクトヒープの問題が発生しました。85,000バイトを超えるオブジェクトは、圧縮されていないラージオブジェクトヒープに配置されるため、メモリ不足の状況が発生する可能性があります。.NET 4のパフォーマンスは明らかに改善されていますが、完璧にはほど遠いです。解決策は、基本的に、静的に割り当てられたメモリのチャンクをいくつか含む独自のバッファプールを使用し、それらを再利用することです。
SOについては、その周りにたくさんの質問があります。

更新:Microsoftは、WCFスタックの一部としてバッファーマネージャーを提供しています。codeprojectにも1つあります。

于 2011-04-17T21:00:12.350 に答える
4

byte []配列の長さはどれくらいですか?それらは小さなオブジェクトまたは大きなオブジェクトのヒープに分類されますか?メモリの断片化が発生した場合、それらはLOHに分類されます。

したがって、同じバイト配列を再利用するか(プールを使用)、より小さなチャンクを使用する必要があります。LOHは圧縮されないため、かなり断片化される可能性があります。悲しいことに、これを回避する方法はありません。(この制限を知り、それを回避することは別として)

于 2011-04-17T21:03:07.433 に答える
0

GCは大きなオブジェクトヒープを圧縮しませんが、プログラムで圧縮することができます。次のコードスニペットは、これを実現する方法を示しています。

GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
于 2018-06-03T04:44:56.003 に答える