web-dev-qa-db-ja.com

メモリを多用するアプリケーションでメモリ不足を回避するための戦略

私のC#.NETアプリケーションは、多くのファイルを電気的に読み取る必要があります。いくつかの計算を行う必要があり、出力ファイルを生成する必要があります。入力の性質上、各入力行の後で、または1つのファイルの後でさえ出力することは非常に非効率的です。そのため、ファイルのチャンクの後に行う方がよいでしょう。

この理由は、各ファイルに1つのタイムスタンプの読み取り値/電気単位のリストが含まれていますが、出力は各単位のファイルである必要があるためです。
たとえば、入力は、たとえば、 1つのタイムスタンプのボルト、アンペア、ワット、ステータスコード(2015_08_31_00_00_00.txt、2015_08_31_00_00_05.txt ...)。
出力は電気ユニットごとである必要があります。 1日1ファイル
(c://ampere/2015_08_31.txt、c://volt/2015_08_31.txt ...)。

これはアプリケーションの簡略図です。実際には、いくつかの異なる入力および出力形式、ディレクトリ構造などがあります。

私がやりたいことは、計算された出力値をメモリに保持し、さまざまな戦略に従って出力することです。これは、たとえばすべての入力ファイルが処理されるまで。

このようないくつかの戦略では、メモリ内のデータが多すぎる可能性があるため、メモリの使用状況を監視し、より早く出力する必要があるかどうかを判断します。

プログラムの使用済みメモリを取得する方法を知っていますですが、使用可能なメモリの見積もりを安全に取得するにはどうすればよいですか?

私が理解している限り、これはメモリの断片化、ページング、トラッシュなどのために簡単な作業ではありません。この場合、現在のビルド設定で32ビットのメモリ制限が発生したことはわかりますが、64ビットプログラムにも適用できる一般的な答えを得たいと思います。

ディスクに書き込むのに十分なメモリがまだ利用可能であるが、適切な量のRAMを使用してI/Oを最適化する場合、

更新
まだこの機能を実装していないため、通常の状況でメモリの問題が発生するかどうかはわかりません。あなたのすべてのコメントと回答のおかげで、それは簡単には達成できないと思います。

私の現在の考えは、入力ファイルのサイズに基づいて固定入力制限を使用することです。他のプログラムが重い負荷を作成する場合、これはまだ問題から保護しません。各ファイルは常に数KBです。

SQLiteのアイデアは覚えておきますが、OKかどうかを確認する必要があります

3
John

残念ながら、「RAMプログラムが使用していますか?)」または「OutOfMemoryExceptionの壁にどれだけ近づくのですか?」という質問に答える良い方法はありません。これには多くの理由があります。実際よりもずっと複雑です。

ただし、不必要に入力データを保持していないことを確認することをお勧めします。たとえば、データの処理方法によっては、ファイルを読み取り、関連する計算を一度に1行ずつ、または一度に1行ずつ実行することが可能です。結果の集計を続けても、入力データを保持しない場合は、メモリ使用量を抑えることができます。

それでも効果がない場合は、結果が積み重なるだけなので、それを処理する最良の方法は、それらをメモリからオフロードすることです。たとえば、それらをリレーショナルデータベースに入れると、入ってくるのと同じ速さで、代わりにディスクに格納されます。そして、一日の終わりに、その日の結果を取り込むクエリを実行し(ヒント:レコードを挿入するときに設定されるタイムスタンプフィールドがある場合、これははるかに簡単です)、それらを最終バージョンに保存します。出力ファイル内。

7
Mason Wheeler

system.Diagnostics名前空間の パフォーマンスカウンター を使用できます。
categoryNameが "Memory"でcounterNameが "Available Bytes"の2つの文字列コンストラクターを使用します。その後、次のようなものを使用できます
long availableBytes = Convert.ToInt64(myPerformanceCounter.NextValue())読み取り値を取得します。
それよりも多くの情報が必要な場合は、さまざまなカテゴリとカウンターを試してみてください。
重要な注意:PerformanceCounterクラスはIDisposableインターフェースを利用するため、必ずラップするかusingステートメントで実行するか、完了したらDispose()メソッドを呼び出します。

2
TheHitchenator

出力に必要なスペースの最大量がわかっていて、それがアドレススペースに収まる場合は、VirtualAlloc()などの関数を使用して、ページのコミットの有無にかかわらず、メモリアドレスの範囲を予約できます。実際に書き込みを試みるまで、物理ページは割り当てられません。したがって、メモリ領域を予約するためだけにメモリ不足エラーが発生することはありません。入力ファイルをメモリマップファイルとして開くこともできるため、OSは物理ページを読み取るときにディスクからのみ物理ページをコピーします。

その時点で、メモリを割り当てるために追加の呼び出しを行う必要はありません。物理メモリが不足すると、OSは仮想メモリに使用していないページをページアウトするか、VirtualFree()を実行できます。それらが書かれた後のページ。

0
Davislor