为什么要将多个小字节数组写入文件比写一个大数组要快?

时间:2012-07-11 14:58:15

标签: c# arrays performance io

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

  

测试编写许多数组
  331.6902 ms
  测试写大阵列
  14756.7559毫秒

对于此测试,“many arrays”实际上是一个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倍。 ..为什么?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

原因很可能是单个1MB阵列被保存在主内存中,但1GB阵列被换成了磁盘。

因此,当单个数组写入1024次时,您正在从内存写入磁盘。如果目标文件是连续的,则硬盘驱动器头在此过程中不必移动很远。

写入1GB阵列一次,你正在从磁盘读取到内存然后写入磁盘,很可能导致每次写入至少有两个HDD磁头移动 - 首先从交换文件中读取块,然后返回到目标写文件。

答案 2 :(得分:0)

它可能与操作系统处理文件写入的方式有关。使用单write次调用写入1GB时,OS必须暂停写入多次,以允许其他进程使用磁盘I / O.而且你也不是在缓冲写作。您可以通过指定更大的bufferSize来优化速度。

public FileStream(
    SafeFileHandle handle,
    FileAccess access,
    int bufferSize
)