6

ディスク上のファイルを読み書きする小さなプログラムがあります。最も単純なレベルに分解すると、1 つのファイル ストリームからバイトを読み取り、別のファイル ストリームに書き込みます。それはその義務をうまく果たしますが、最速のものではありません。

1ギガバイト以上の読み取り/書き込みを驚異的な速度で処理できる他のアプリケーションを見てきました。明らかに、それらは小さな .NET アプリよりも金属に近い動作をしています。

ディスクとの間でストリーミングするための最も効率的な .NET API は何ですか? 迅速なディスク アクセスに使用できる (そして呼び出す価値のある) win32 API は何ですか?

4

4 に答える 4

12

高速ファイル I/O は、特定の API 呼び出しに関するものではなく、I/O で動作するようにアプリケーションを設計する方法に関するものです。

たとえば、すべての I/O 操作を 1 つのスレッドで順次実行している場合

  1. ブロックをメモリに読み込む
  2. 何らかの方法でメモリ内のブロックを処理する
  3. ブロックをファイルに書き出す
  4. 完了するまで繰り返します...

単一スレッドの処理ループでシステムの I/O 帯域幅のボトルネックになっています。別のより複雑な設計は、アプリケーションをマルチスレッド化してスループットを最大化し、待ち時間を回避することです。これにより、システムは CPU と I/O コントローラの両方の帯域幅を同時に利用できます。このための典型的な設計は次のようになります。

  1. 1 つ (または複数) のワーカー スレッドがディスクからデータを読み取り、それらを共有入力キューに追加します。
  2. 1 つ (または複数) のワーカー スレッドが共有入力キューからブロックを読み取り、それらを処理して共有出力キューに追加します。
  3. 1 つ (または複数) のワーカー スレッドが、ブロックされた処理を共有出力キューから読み取り、適切な出力ファイルに書き込みます。

これは適切に設計するのが容易なアーキテクチャではなく、メモリー内のロック競合の発生を回避したり、同時 I/O 要求でシステムを圧倒したりするために、かなりの考慮が必要です。また、出力処理の状態がスレッドのコール スタックではなく、入出力作業キューで管理されるように、制御メタデータを提供する必要があります。また、マルチスレッド I/O では、作業が入力キューに確実な順序で配置されていることを確認できないため、正しい順序で出力を変換して書き込むことも確認する必要があります。これは複雑ですが、可能であり、シリアル アプローチと比較してスループットに劇的な違いが生じる可能性があります。

本当に時間があり、システムからすべてのパフォーマンスを引き出したい場合は、I/O 完了ポート(比較的低レベルの API) を使用してスループットを最大化することもできます。

幸運を。

于 2009-07-06T15:16:27.957 に答える
7

.NET file support is fast enough (comparable to native Win32 functions). Several options that can help you improve your performance:

  1. If your read/write is sequential, help the caching manager by applying appropriate strategy - provide RandomAccess or SequentalScan, when instantiating FileStream
  2. Consider using a larger memory buffer for storing read data
  3. If you copy many small files, you can first read many files into a memory buffer at once (see 2), and then write the files to disk
  4. If source and destination streams are located in different places (that is, not on the same hard drive, maybe one file on the network, the other on a local hard drive, etc.), you can use the asynchronous pattern to speed-up, read data by using BeginRead, then write data using BeginWrite, and while data is being written read next data block using BeginRead.
  5. If you still think that performance is not enough (however from my test it is equatable or even faster than the internal Windows copy), you can use the CopyFileEx Win32 function (but this function works with files, not streams).
于 2009-07-06T09:10:06.667 に答える
0

ディスクI/Oがボトルネックであったかどうかを判断するために、アプリケーションのプロファイルを作成しましたか?

これを実行しているハードウェアの種類は何ですか?ハードウェア構成は何ですか?

.NETでは、System.IO.File名前空間を試すことができます。

Win32関数の場合は、CreateFile、WriteFile、ReadFileシリーズを試すことができます。

例:

http://msdn.microsoft.com/en-us/library/bb540534(VS.85).aspx

これは絶対にカットして乾燥させません。テストと測定がすべてです。

于 2009-07-05T22:16:43.360 に答える
0

BinaryReaderBinaryWriter適切なバッファサイズを使用すると、かなり高速になります。構造体を読み込んでいる場合、この記事で説明されている安全でないアプローチを使用すると、すばやく読むことができます。書き込みも同様です。また、I/O が実際にボトルネックであることを再確認するという提案にも同意します。そのような間違いのために、私は最初にその記事に出くわしました。

于 2009-07-05T22:55:49.290 に答える