5

我做了一个测试,看看在磁盘上从单字节数组写入 1GB 文件和从 1024 个数组(每个 1MB)写入另一个 1GB 文件所需的时间是否存在差异。

测试写入多个数组
331.6902 ms
测试写入大数组
14756.7559 ms

对于这个测试,“许多数组”实际上是一个单独的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

我认为造成巨大差异的主要原因是操作系统设法缓存了您在小块中执行的几乎整个 1GB 写入。

您需要更改设置基准的方式:代码应该写入相同的数据,第一次写入 1024 个块,第二次写入一个块。您还需要通过指定来关闭操作系统中的数据缓存FileOptions.WriteThrough,如下所示:

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 数组一次,您是从磁盘读取到内存然后写入磁盘,很可能导致每次写入至少两次 HDD 磁头移动 - 首先从交换文件中读取块,然后返回目标文件写入它。

于 2012-07-11T15:43:20.087 回答
0

它可能与操作系统如何处理文件写入有关。当使用单个write调用写入 1GB 时,操作系统将不得不多次暂停写入以允许其他进程使用磁盘 I/O。而且您也没有缓冲写入。您可以通过指定更大的 bufferSize 来优化速度。

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