10

我正在阅读二进制文件,这是一个示例:

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16*1024];
    int read;
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        ......
    }

}

显然缓冲区大小(16*1024)对性能有很大的影响。我读过它取决于 I/O 技术(SATASSDSCSI等)以及文件所在分区的片段大小(我们可以在格式化分区时定义)。

但这里有一个问题: 是否有任何公式或最佳实践来定义缓冲区大小?现在,我正在根据反复试验进行定义。

编辑: 我已经在我的服务器上测试了不同缓冲区大小的应用程序,我得到了 4095*256*16 (16 MB) 的最佳性能!!!4096 慢了 4 秒。

以下是一些非常有用的旧帖子,但我仍然无法理解原因:

4

2 回答 2

7

Sequential File Programming Patterns and Performance with .NET ”是 I/O 性能改进方面的一篇很棒的文章。

PDF 文件的第 8 页中,显示缓冲区大小大于 8 个字节的带宽是恒定的。考虑到这篇文章写于 2004 年,硬盘驱动器是“ Maxtor 250 GB 7200 RPM SATA disk ”,最新的 I/O 技术结果应该会有所不同。

如果您正在寻找最佳性能,请查看pinvoke.net或 PDF 文件的第 9 页,无缓冲文件性能测量显示更好的结果:

在无缓冲 I/O 中,磁盘数据直接在应用程序的地址空间和设备之间移动,无需任何中间复制。

概括

  • 对于单个磁盘,使用 .NET 框架的默认值——它们为顺序文件访问提供了出色的性能。
  • 创建文件时预分配大型顺序文件(使用 SetLength() 方法)。与碎片文件相比,这通常将速度提高约 13%。
  • 至少目前,磁盘阵列需要非缓冲 I/O 才能获得最高性能——缓冲 I/O 可能比非缓冲 I/O 慢八倍。我们预计此问题将在 .NET 框架的后续版本中得到解决。
  • 如果您自己进行缓冲,请使用较大的请求大小(64 KB 是一个不错的起点)。使用 .NET 框架,单个处理器可以使用非缓冲 I/O 以超过 800 Mbytes/s 的速度读取和写入磁盘阵列。
于 2013-11-07T13:29:18.727 回答
4

没有最佳最差的缓冲区大小,但您必须查看某些方面。

由于你使用的是 C#,所以你在 Windows 上运行,Windows 使用NTFS,它的页面大小是 4 MB,所以建议使用 4096 的倍数。所以你的缓冲区大小是16*1024 = 4*4096,这是一个不错的选择,但要说如果它比16*4096我们说的好还是坏。

一切都取决于情况和程序的要求。请记住,您无法选择最佳选项,而只能选择更好的选项。我建议使用4096,但您也可以使用自己的4*4096,甚至可以使用16*4096,但请记住,此缓冲区将在堆上分配,因此分配需要一些时间,因此您不想分配大缓冲区,例如128*4096

于 2013-10-24T06:30:12.367 回答