2012-01-01 6 views
2

私はディスクに書き込むファイルがたくさんある、私はパフォーマンスを向上させるためにディスクキャッシュを無効にしたい、私はGoogleの検索ソリューションを見つける:Win32 CreateFileメソッドFILE_FLAG_NO_BUFFERINGとHow to empty/flush Windows READ disk cache in C#?があります。どのようにディスクキャッシュを無効にするにはC#を呼び出すWin32ファイルFILE_FLAG_NO_BUFFERINGでCreateFile APIを

私は、テストするコードの少しを書くかどうか働いたことができます。

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操作をサポートするために開かれていなかった、私はこの記事When you create an object with constraints, you have to make sure everybody who uses the object understands those constraintsを見つけましたが、私は完全に理解することはできませんので、私はテストに私のコードを変更します。

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」のバイト数がall.iでないことが必要です。ブロックサイズを1またはその他の整数(512倍ではない)に変更しようとしているときに同じエラーが発生します.i win32 WriteFile apiも同じエラー誰かが私を助けることができますか?バッファなしモードで

+1

あなたはそれがFileOptions.WriteThroughとして利用可能である、のPInvokeする必要はありません。この方法を書くことは、ディスクを待たなければならないので、ずっと遅くなります。 –

+0

デフォルトのオプション(ライトスルーを使用しない)を使用し、60-80kbファイル全体を1回の書き込みで書き込むことをお勧めします。 –

答えて

4

のCreateFile()関数は、何をやってもしなくてもよいものにstrict requirementsを課します。特定のサイズ(デバイスセクタサイズの倍数)のバッファを持つことがその1つです。

さて、あなたはファイルを向上させることができ、あなたのコード内でバッファリングを使用する場合にのみ、このように書いています。バッファリングせずに10バイトを書きたい場合は、No Bufferingモードでは役に立ちません。

+0

ははい、私は秒(秒あたりに25個のファイル)ごとにファイルがたくさんあるthanks.if、ファイルの平均サイズは60-80kで、私はバッファを使用しない行うことができて? – springchun

+0

@ user902408あなたの特定のシナリオでは、バッファリングモードは役に立ちません。このモードは、例えば、たくさんのタグやその他のデータが小さな部分に書き込まれた巨大なXMLファイルの生成では問題ありません。しかし、60-80 kbの大容量ファイルの場合、多くの利点はありません。 –

+0

@ user902408ファイルをさらに処理することに応じて、仮想ファイルシステム(ファイル内のFS)はバッファリングレベルを提供し、ディスク上の1つの大きなファイルバッファリング(あなたが望むように)。 –

1

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

は、メモリ内のデータとディスク上の目的のファイルを持っているオブジェクトとキューを作成します。 あなただけのメモリーに最初のファイルの書き込みを開始し、その後、別のスレッドで、IO-完了ポートベースのファイルストリームハンドル(のisAsync = true)を開いて、キューを経由開始 - ちょうどいくつかのポイントあなたのようにそれらのあまりに多くを開けないでくださいおそらく、キャッシュの破棄などのためにperfを失い始めるでしょう。あなたのシステムとssdの最適な量が何であるかを見るためにプロファイルする必要があります。

各オープンした後、あなたは非同期ファイルストリームのメソッドを使用することができますが開始...ファイルにメモリからのデータの書き込みを開始します。 isAsyncにはいくつかの要件があるため、filestreamを通常どおり使用すると、あらゆるコーナーケースで作業するのが簡単ではない場合があります。

ファイルの作成に別のスレッドを使用した場合と、非同期APIを使用して別のスレッドを使用して書き込む場合の改善の有無は、ファイルの作成/オープンがブロックされる可能性がある場合のみです。 SSDはデータへのアクセスを高速に保つために内部的にさまざまな処理を行います。このような極端なパフォーマンスを開始すると、SSDコントローラ間に大きな違いが生じることがあります。また、コントローラドライバがうまく実装されていないと、OS/Windowsが低速または凍結し始める可能性があります。ハードウェアのベンチマークサイトでは、このような種類のシナリオ(例えば、x KBを作成して100万のファイルに書き込むなど)に重点を置いているわけではありません。

関連する問題