5

単一バイト配列からディスクに 1GB ファイルを書き込むのにかかる時間と、1024 個の配列 (それぞれ 1MB) から別の 1GB ファイルを書き込むのにかかる時間に違いがあるかどうかを確認するテストを行いました。

多くの配列のテスト書き込み
331.6902 ミリ秒
大きな配列のテスト書き込み
14756.7559 ミリ秒

このテストでは、「多くの配列」は実際にはbyte[1024 * 1024]、for ループを使用して 1024 回書き込む単一の配列です。「大きな配列」は、ランダムな値で満たされた 1GB のバイト配列です。

コードは次のようになります。

Console.WriteLine("Test Writing many arrays");

byte[] data = new byte[1048576];

for (int i = 0; i < 1048576; i++)
    data[i] = (byte)(i % 255);

FileStream file = new FileStream("test.txt", FileMode.Create);

sw1.Restart();

for (int i = 0; i < 1024; i++ )
     file.Write(data, 0, 1048576);

file.Close();
sw1.Stop();
s1 = sw1.Elapsed;
Console.WriteLine(s1.TotalMilliseconds);

Console.WriteLine("Test Writing big array");


 byte[] data2 = new byte[1073741824];

 for (int i = 0; i < 1073741824; i++)
      data2[i] = (byte)(i % 255);

 FileStream file2 = new FileStream("test2.txt", FileMode.Create);

 sw1.Restart();

 file2.Write(data2, 0, 1073741824);

 file2.Close();
 sw1.Stop();

 s1 = sw1.Elapsed;
 Console.WriteLine(s1.TotalMilliseconds);

メソッドを呼び出してストリームをディスクに書き込むfile.Close()ため、時限部分の中に を含めました。Flush()

結果のファイルはまったく同じサイズです。

C# は、私が常に同じ配列を使用していること認識し、反復/書き込みプロセスを最適化する可能性があると考えましたが、結果は 2 ~ 3 倍ではなく、約 45 倍高速です...なぜですか?

4

3 に答える 3

5

大きな違いの主な理由は、OSが、小さなチャンクで行う1GBの書き込みのほぼすべてをキャッシュできることだと思います。

ベンチマークの設定方法を変更する必要があります。コードは、最初は1024チャンクで、2回目は1つのチャンクで同じデータを書き込む必要があります。FileOptions.WriteThroughまた、次のように指定して、OSでのデータのキャッシュをオフにする必要があります。

var sw1 = new Stopwatch();
Console.WriteLine("Test Writing many arrays");
var data = new byte[1073741824];
for (var i = 0; i < 1073741824; i++)
    data[i] = (byte)(i % 255);
var file = new FileStream("c:\\temp\\__test1.txt", FileMode.Create, FileSystemRights.WriteData, FileShare.None, 8, FileOptions.WriteThrough);
sw1.Restart();
for (int i = 0; i < 1024; i++)
    file.Write(data, i*1024, 1048576);
file.Close();
sw1.Stop();
var s1 = sw1.Elapsed;
Console.WriteLine(s1.TotalMilliseconds);
Console.WriteLine("Test Writing big array");
var file2 = new FileStream("c:\\temp\\__test2.txt", FileMode.Create, FileSystemRights.WriteData, FileShare.None, 8, FileOptions.WriteThrough);
sw1.Restart();
file2.Write(data, 0, 1073741824);
file2.Close();
sw1.Stop();
s1 = sw1.Elapsed;
Console.WriteLine(s1.TotalMilliseconds);

このコードを実行すると、結果は次のようになります。

Test Writing many arrays
5234.5885
Test Writing big array
5032.3626
于 2012-07-11T15:17:22.797 に答える
1

その理由は、単一の1MBアレイがメインメモリに保持されているが、1GBアレイがディスクにスワップアウトされたことが原因である可能性があります。

したがって、単一の配列を1024回書き込むときは、メモリからディスクに書き込んでいました。宛先ファイルが連続している場合、このプロセス中にHDDヘッドを遠くに移動する必要はありません。

1GBアレイを一度書き込むと、ディスクからメモリに読み取り、次にディスクに書き込みます。おそらく、書き込みごとに少なくとも2つのHDDヘッドの動きが発生します。最初にスワップファイルからブロックを読み取り、次に宛先ファイルに戻って書き込みます。それ。

于 2012-07-11T15:43:20.087 に答える
0

OS がファイル書き込みを処理する方法に関連している可能性があります。単一のwrite呼び出しを使用して 1GB を書き込む場合、OS は書き込みを何度も一時停止して、他のプロセスがディスク I/O を使用できるようにする必要があります。また、書き込みをバッファリングしていません。より大きな bufferSize を指定することで、速度を最適化できます。

public FileStream(
    SafeFileHandle handle,
    FileAccess access,
    int bufferSize
)
于 2012-07-11T15:54:33.830 に答える