2

みんな、私は毎秒ディスクにたくさんのファイルを書き込みます、私はパフォーマンスを改善するためにディスクキャッシュを無効にしたいです、私は解決策を見つけます:FILE_FLAG_NO_BUFFERINGでwin32CreateFileメソッドとC#でWindowsREADディスクキャッシュを空/フラッシュする方法?

うまくいくかどうかをテストするためのコードを少し書きます。

const int FILE_FLAG_NO_BUFFERING = unchecked((int)0x20000000);

[DllImport("KERNEL32", SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
static extern SafeFileHandle CreateFile(
      String fileName,
      int desiredAccess,
      System.IO.FileShare shareMode,
      IntPtr              securityAttrs,
      System.IO.FileMode  creationDisposition,
      int                 flagsAndAttributes,
      IntPtr              templateFile);

static void Main(string[] args)
{
    var handler = CreateFile(@"d:\temp.bin", (int)FileAccess.Write, FileShare.None,IntPtr.Zero, FileMode.Create, FILE_FLAG_NO_BUFFERING, IntPtr.Zero);
    var stream = new FileStream(handler, FileAccess.Write, BlockSize);//BlockSize=4096
    byte[] array = Encoding.UTF8.GetBytes("hello,world");
    stream.Write(array, 0, array.Length);
    stream.Close();
}

このプログラムを実行すると、アプリケーションで例外が発生します。IO操作は機能しません。ファイルが長くなるか、同期IO操作をサポートするためにハンドルが開かれなかった可能性があります

後で、この記事を見つけました。制約付きのオブジェクトを作成するときは、オブジェクトを使用するすべての人がそれらの制約を理解していることを確認する必要がありますが、完全には理解できないため、コードを変更してテストします。

var stream = new FileStream(handler, FileAccess.Write, 4096);
byte[] ioBuffer = new byte[4096];
byte[] array = Encoding.UTF8.GetBytes("hello,world");
Array.Copy(array, ioBuffer, array.Length);
stream.Write(ioBuffer, 0, ioBuffer.Length);
stream.Close();

正常に実行されていますが、すべてではなく「hello、world」バイトが必要です。ブロックサイズを1または他の整数(512倍ではない)に変更しようとすると同じエラーが発生します。win32WriteFileapiも同じエラーが発生します。誰かが私を助けることができます?

4

2 に答える 2

4

バッファリングなしモードのCreateFile()関数は、実行できることと実行できないことについて厳格な要件を課します。特定のサイズ(デバイスセクターサイズの倍数)のバッファーを持つこともその1つです。

これで、コードでバッファリングを使用する場合にのみ、この方法でファイルの書き込みを改善できます。バッファリングなしで10バイトを書き込みたい場合は、バッファリングなしモードは役に立ちません。

于 2012-01-01T10:16:56.363 に答える
1

私があなたの要件を正しく理解した場合、これは私が最初に試みることです:

メモリ内のデータとディスク上のターゲットファイルを持つオブジェクトでキューを作成します。最初にファイルをメモリに書き込み始め、次に別のスレッドでキューを通過し始め、io-completionポートベースのファイルストリームハンドル(isAsync = True)を開きます-ある時点で開いたファイルの数が多すぎないようにしてください。キャッシュのトラッシングなどが原因でパフォーマンスが低下し始める可能性があります。システムとSSDに最適な量を確認するには、プロファイルを作成する必要があります。

開くたびに、非同期ファイルストリームメソッドBegin ...を使用して、メモリからファイルへのデータの書き込みを開始できます。isAsyncにはいくつかの要件があるため、これは通常のファイルストリームを使用する場合ほど簡単ではありません。

別のスレッドを使用してファイルを作成し、別のスレッドを使用して非同期APIを使用してそれらに書き込むことに改善があるかどうかは、ファイルの作成/オープンがブロックされる可能性がある場合にのみ当てはまります。SSDは、データへのアクセスを高速に保つために内部でさまざまなことを実行するため、この種の極端なパフォーマンスを開始すると、SSDコントローラー間に顕著な違いが生じる可能性があります。コントローラドライバが適切に実装されていない場合、OS/Windowsの動作が遅くなったりフリーズしたりする可能性もあります。ハードウェアベンチマークサイトは、この特定の種類のシナリオ(たとえば、x KBをできるだけ早く作成して100万ファイルに書き込む)を実際に強調しておらず、他のドライバーよりも遅いドライバーが存在することは間違いありません。

于 2014-01-29T16:10:45.350 に答える