【问题标题】:Optimum file buffer read size?最佳文件缓冲区读取大小?
【发布时间】:2010-12-05 20:15:54
【问题描述】:

我正在编写一个需要读取相当大文件的应用程序。我一直想知道现代 Windows XP 计算机上读取缓冲区的最佳大小是多少。我用谷歌搜索并找到了许多以 1024 作为最佳大小的示例。

这是我的意思的一个sn-p:

long pointer = 0;
buffer = new byte[1024]; // What's a good size here ?
while (pointer < input.Length)
{
    pointer += input.Read(buffer, 0, buffer.Length);
}

我的应用程序相当简单,所以我不想编写任何基准测试代码,但想知道常见的尺寸是多少?

【问题讨论】:

标签: .net windows performance


【解决方案1】:

1k 的缓冲区大小似乎有点小。通常,没有“一刀切”的缓冲区大小。您需要设置适合算法行为的缓冲区大小。现在,一般来说,拥有一个非常大的缓冲区并不是一个好主意,但是,拥有一个太小或不符合您处理每个块的方式的缓冲区也不是那么好。

如果您只是在处理之前将数据一个接一个地完全读取到内存中,我会使用更大的缓冲区。我可能会使用 8k 或 16k,但可能不会更大。

另一方面,如果您正在以流方式处理数据,则读取一个块然后在读取下一个块之前对其进行处理,较小的缓冲区可能更有用。更好的是,如果您正在流式传输具有结构的数据,我会更改读取的数据量以专门匹配您正在读取的数据类型。例如,如果您正在读取包含 4 字符代码、浮点数和字符串的二进制数据,我会将 4 字符代码和浮点数读取到 4 字节数组中。我会读取字符串的长度,然后创建一个缓冲区来一次读取整个字符串数据块。

如果您正在进行流数据处理,我会研究 BinaryReader 和 BinaryWriter 类。这些使您可以非常轻松地处理二进制数据,而不必担心数据本身。它还允许您将缓冲区大小与您正在使用的实际数据分离。您可以在底层流上设置一个 16k 的缓冲区,并使用 BinaryReader 轻松读取单个数据值。

【讨论】:

  • 感谢您使用 BinaryReader 的建议。使用 BinaryReader 有助于读取字符串,因为我不需要编写管道代码来写入长度。我将测试 8K 和 16K 读取,看看性能是否有所提高。就个人而言,我不在乎大小,但一些 QA 人员想看看我们是否可以通过更好地利用硬件和操作系统来提高性能。
  • 如果您只是将大量数据流式传输到内存中,您可能会尝试使用更大的缓冲区。只要将缓冲区大小保持为磁盘簇大小的倍数,就应该是最佳的。老实说,我认为我在 90 年代末和 2000 年初的许多做法仍然根深蒂固。如果您运行此程序的系统是现代且高性能的,则 32k、64k 甚至更大的缓冲区可能会有所帮助。如果你变得太大(比如 1mb),你可能会看到收益递减,因为其他因素开始起作用(即交换抖动)。关键是将读取与低级行为相匹配。
【解决方案2】:

取决于您在访问时间和内存使用之间划定界限的位置。缓冲区越大,速度越快 - 但内存成本越高。 读取文件系统集群大小的倍数可能是最有效的,在使用 NTFS 的 Windows XP 系统中,4K 是默认集群大小。

你可以看到这个链接Default cluster size for NTFS, FAT, and exFAT

再见。

【讨论】:

  • 我将尝试@jrista 建议的 8K 和 16K 读取。有趣的是,这篇文章说 Windows 使用 8k 集群用于 16 TB 磁盘分区。我以前从未见过这么大的分区。
  • 安德鲁,8K 和 16K 是 4K 的倍数
  • 旧硬盘一次读取和写入整个 512 字节扇区。现代硬盘一次读取和写入整个 4096 字节扇区。 Windows NTFS 有一个(默认)簇大小为 4096 字节。使用 Windows 事件跟踪,您可以看到 Windows 最常为 16,384 字节和 4,096 字节(以及在较小程度上的 819249152 字节)执行实际硬盘驱动器 I/O。理想情况下保持为 4k 的倍数,即 16384 字节。
猜你喜欢
  • 2018-10-14
  • 2012-11-06
  • 1970-01-01
  • 2013-03-10
  • 2013-11-02
  • 2014-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多