2

配列のメモリの一部をシステムに返す効果的な方法はありますか? 私は C# を使用して、1 つの大きな文字列配列とハッシュテーブル (>100k 要素) を反復処理しています。個々の要素を使い終わった後、null に設定しています。さまざまなレベルで、ループ全体でガベージ コレクターを呼び出して実験しましたが、システムにメモリを返すものはありません (ガベージ コレクターを完全に呼び出し、保留中のファイナライザーを待機すると、コードが非常に遅くなり、応答しなくなります)。
配列をn個の部分に分割し、各部分が終了した後にgcを呼び出すことを考えましたが、それは面倒です

GC.Collect(1);
GC.Collect(2);
....
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
4

3 に答える 3

2

ガベージコレクターに任せてください。最も効率的なアプローチは、GC がすでに行っていることとまったく同じです。つまり、実際に実行する必要があるまでコレクションを延期します。そうすれば、必要以上に多くのコレクションを行う必要がなくなり、すべてのメモリ再利用作業を比較的少数の収集呼び出しにまとめることができるため、オブジェクト グラフを必要以上に頻繁にトラバースする必要がなくなります。

オブジェクトへの参照をすべてクリアしてください。誤って必要以上に長く存続させないようにしますが、それを行っている限り、他に何もする必要はありません。

于 2012-04-09T21:48:52.447 に答える
0

一部の非常に特殊で例外的な状況を除いて、最善のポリシーは、ガベージコレクターを独自のスケジュールで動作させることです。これは高度に調整されたソフトウェアであり、CLRの内部動作について、あなたや私が持っているよりもはるかに多くの知識を持っており、ほとんどの場合、私たちよりも優れた決定を下します。

オブジェクトを使い終わった後にオブジェクトによって消費されるメモリが心配な場合は、作業を終了するときに個々の配列要素を無効にすることができます(オブジェクトをより早く収集できるようにする可能性があります)。

さらに重要なことに、すべてのデータを一度にメモリに保持する必要がありますか?一度に少しだけロードすることは可能ですか?たとえば、ファイルからインクリメンタルに読み取ることはできますか?もしそうなら、あなたは間違いなくあなたの配列をに置き換えるオプションがあり、IEnumerable<T>必要に応じてデータを怠惰にロードし、それが終わったら自動的にそれを忘れることができます。このアプローチは、わずかな追加の計算を犠牲にして、メモリ消費を抑えることが保証されています。

于 2012-04-09T22:02:48.543 に答える
0

文字列を配列に格納すると、文字列を反復処理している間、文字列はすべてメモリに残ります。

実際の反復では、メモリの負荷はそれほど増加しません。作成する新しいオブジェクトは、効率的にガベージコレクションされます。

null配列の特定のケースでは、一度読み取った配列エントリをに設定できます。私はそれに反対することをお勧めします:メモリ不足の問題なしに反復の開始を生き残ることができれば、おそらく残りの部分も生き残るでしょう。配列が不要になったら、配列へのすべての参照を必ずnullにしてください。デバッグ中に、配列が参照されなくなったと思われるポイントにGC.Collect()を追加できます。割り当てられたメモリの大幅な低下を観察する必要があります。これが発生しない場合は、他の場所で配列への参照、または配列コンテンツへの参照があります。

ハッシュテーブルの場合、このアプローチはまったく機能しません。エントリを反復処理している間は、ハッシュテーブルからエントリを安全に削除することはできません。

さて、ハッシュテーブルを使用している場合、これはアイテムの順序をあまり気にしないことを意味します。その場合、配列やハッシュテーブルに保持せずに、データの読み取り時にアルゴリズムを処理するようにアルゴリズムを作り直すことができます。

于 2012-04-09T22:04:41.953 に答える