7

.NET3.5アプリケーションを使用しています

  • 関数が100万回実行されている
  • 1MB以上の文字列(異なるサイズの文字列)で検索、置換、正規表現の操作を実行します

アプリケーションのプロファイルを作成すると、これらの文字列がLOHに保存されていることを確認できますが、後でGCによって再利用されるため、特定の時点で最大10個の文字列のみがLOHにあります(10スレッドが実行されています)。

私の理解では、これらの大きな文字列はLOHに配置され、GCによって再利用されますが、割り当て場所が原因で(LOHにあるため、圧縮されないため)、断片化が発生します。これは、操作中にメモリリークがないにもかかわらず発生しています。

約100K回は問題を引き起こしませんが、100万回以上に達すると、メモリ不足の例外が発生します。

私はANTSMemoryProfilerを使用していますが、これは初期の実行で得られた結果です。

.NET Using 70MB of 210MB total private bytes allocated in to the application
Number of Fragments: 59
Number of Large Fragments : 48 (99.6% of free memory)
Largest Fragment: 9MB
Free Space: 52% of total memory  (37MB)
Unmanaged Memory: 66% of total private memory (160MB)
  1. 手元のデータに基づいて、私の診断は正しいと思いますか?
  2. もしそうなら、どうすればこのLOHフラグメンテーションの問題を解決できますか?私はそれらの文字列を処理する必要があり、それらは大きな文字列です。それらを分割してそのように処理する方法を見つける必要がありますか?その場合、分割文字列で正規表現などを実行することは非常に困難です。
4

1 に答える 1

2
  1. はい。それは正しいですね。LOH が断片化しているため、ランタイムが大きな文字列に十分な連続スペースを割り当てることができません。

  2. いくつかのオプションがあります。最も簡単で効果的な方法を選択することをお勧めします。それはすべて、その書き方に完全に依存します。

    1. 文字列を十分に小さいチャンクに分割して、LOH に含まれないようにします。(85K 未満 - 注: オブジェクトが LOH に配置されたときのロジックはそれほど簡単ではありません。) これにより、GC がスペースを再利用できるようになります。これで断片化が修正されるとは限りません。それ以外の場合でも確実に発生する可能性があります。文字列を小さくしても、LOH になると、問題が先延ばしになります。100 万を超える文字列を処理する必要があるかどうかによって異なります。もう1つの欠点は、文字列をメモリにロードして分割する必要があるため、とにかくLOHになることです。アプリケーションが文字列をロードする前に、文字列を縮小する必要があります。キャッチ22の一種。編集: コメントの Gabe は、文字列を最初にロードできる場合StringBuilder、カバーの下で、LOH から物事を遠ざけるために十分な努力をすることを強調しています (呼び出すまでToString)。

    2. 文字列の処理を別のプロセスに分割します。スレッドの代わりにプロセスを使用します。各プロセスを使用して、たとえば 10K 文字列を処理し、プロセスを強制終了して別のプロセスを開始します。このようにして、各プロセスは白紙の状態から始まります。これの利点は、文字列処理ロジックを変更せず (処理のために文字列を小さくできない場合)、#1 の catch-22 を回避できることです。欠点は、おそらくアプリケーションに大きな変更を加え、マスター プロセスとスレーブ処理プロセス間の作業を調整する必要があることです。トリックは、マスターが大きな文字列がどこにあるかを伝えることしかできず、直接与えることはできないということです。それ以外の場合は、catch-22 に戻ります。

于 2011-09-11T02:55:11.293 に答える