4

約100Mbの巨大なファイルがあります。それらをメモリ(RAM)にロードし、処理してどこかに保存したいと思います。

同時に、メモリ使用量の制限が存在することを望んでいます。たとえば、100Mbの場合、私のアプリはこのメモリ制限を超えて使用しません。制限を超えると、ファイルはパーツを処理します。

これについての私の理解:

var line = file.ReadLine();
var allowed = true;

while( allowed && line != null ) 
{
   var newObject = new SomeObject( line );
   list.add( newObject );

   // Checking the memory
   allowed = CheckUsedMemory(); 

   line = file.ReadLine()
} 

RAMの使用を制限するにはどうすればよいですか?CheckUsedMemoryメソッドを実装する方法は?ありがとうございました。

UPD

皆さん、良いアドバイスをありがとうございました。

4

5 に答える 5

6

あなたはで試すことができます:

long usedMemory = GC.GetTotalMemory(true);

また

long usedMemory = GC.GetTotalMemory(false);

1つ目は、メモリのガベージコレクション(クリーニング)を強制するため、低速(ミリ秒)になります。

次に、これを読んで、マシンに搭載されているメモリの量を確認します。

コンピュータに搭載されているRAMの総量をどのように取得しますか?

32ビットアプリとして実行している場合、すべてのメモリを使用することはできず、他のプロセスがメモリを使用している可能性があることに注意してください。

于 2011-02-20T10:33:32.467 に答える
5

まず、メモリ消費量を認識していただきありがとうございます。より多くのプログラマーがとても思いやりがあったとしたら。

第二に、私は気にしません。おそらく、ユーザーはアプリケーションをできるだけ速く実行したいと考えており、結果を5%速くするために8000メガバイトのメモリを消費することをいとわないでしょう。それらをしましょう。:)

ただし、プロセスでより多くのディスクアクセスを強制すると、アプリケーションが使用するメモリの量を人為的に制限すると、処理時間が大幅に増加する可能性があります。誰かがメモリに制約のあるシステムで実行している場合、スワッピングのためにすでにディスクトラフィックが発生している可能性があります。実際にメモリを使い終える前に人為的にメモリをダンプしている場合は、ディスクIOにさらに貢献しているだけです。スワッピングの方法。OSにこの状況を処理させます。

最後に、ここで記述したアクセスパターン(シーケンシャル、一度に1行ずつ)は非常に一般的であり、.NET設計者は、このパターンからメモリ使用量を最小限に抑えるために多大な労力を費やしていることは間違いありません。内部ツリーにオブジェクトを部分的に追加することは良い考えですが、これから実際に恩恵を受けるアプリケーションはほとんどありません。(マージソートは、部分的な処理から大きな恩恵を受ける優れたアプリケーションの1つです。)

完成したオブジェクトのリストで何をしているのかによっては、リスト全体を一度に操作しても改善できない場合があります。または、それを分解することで大きなメリットが得られる場合があります。(Map Reduceがデータ処理の問題をうまく説明している場合は、物事を分解することでメリットが得られるかもしれません。)

いずれにせよ、処理を分割するタイミングを決定するためのベンチマークとして「メモリ」を使用するのは少し気が進まないでしょう。「1000行の入力」または「10レベルのネスト」または「工作機械の実行」を使用したいのです。消費されたメモリの二次的影響ではなく、入力に基づく5分間」など。

于 2011-02-20T10:57:38.250 に答える
2

通常の手順では、すべてをメモリにロードするのではなく、ファイルをチャンクで読み取り、処理して保存します。何らかの理由ですべてをRAMに保持する必要がある場合(たとえば、並べ替えのため)、より多くのRAMに投資する必要があるかもしれません。

これは使用しているアルゴリズムの問​​題であるため、メモリをあまり使用せずに特定のタスクを解決する方法について質問する必要があります。

GC.GetTotalMemory()は、使用しているメモリの量を示します。

現在、100MBのRAMはそれほど多くありません。それをメモリに読み込んで処理し、ディスクに戻すことは非常に高速になります。とにかく、ディスクからメモリにコピーしてディスクに戻すことは避けられないことを忘れないでください。StringBuilder(Stringではなく)を使用して保持することは、必ずしもアプリに過度のオーバーヘッドを追加するわけではありません。1回の操作で100MBを書き込む方が、一度に1行よりも確実に高速です。

于 2011-02-20T11:03:22.590 に答える
1

メモリ使用量を実際に制限することはできません。予約しておくメモリの量のみを制限できます。残りのメモリが解放されるかどうかは、ガベージコレクター次第です。

したがって、処理する前に、現在バッファリングしている行数(またはできれば文字数)だけに関心を持っておくことをお勧めします。

コメントの中で、人々はあなたがファイルを一行ずつ読むべきだと提案しました。一度に1行ずつファイルを処理できると仮定すると、非常に良いアドバイスです。オペレーティングシステムはとにかくファイルをキャッシュするので、パフォーマンスが低下することはありません。

于 2011-02-20T10:41:12.323 に答える
1

ファイルを1行ずつ処理したいように見えますが、.NET 4では、メモリマップトファイルを使用できるため、大きなファイルにまばらにアクセスできることを知っておくと役立つ場合があります。

于 2011-02-20T10:47:39.893 に答える