最佳文件缓冲读取大小?

20

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

这是我所说的一小段:

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

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


这可能会有帮助:https://dev59.com/8WIk5IYBdhLWcg3wIq9U#19837238?noredirect=1#19837238 - Amir Pournasserian
2个回答

9
一个1k的缓冲区大小似乎有点小。通常,不存在“一刀切”的缓冲区大小。您需要设置一个适合您算法行为的缓冲区大小。通常来说,拥有一个非常大的缓冲区不是个好主意,但是,一个太小或者不符合您处理每个块的方式的缓冲区也不是那么好。
如果您只是将数据一块块地读入内存,然后全部处理,那么我会使用更大的缓冲区。我可能会使用8k或16k,但不会超过这个值。
另一方面,如果您正在以流式处理数据的方式进行数据处理,即读取一块数据并在读取下一个之前处理它,较小的缓冲区可能更有用。更好的方法是,如果您要流式传输具有结构的数据,则应更改读取的数据量以特别匹配您正在读取的数据类型。例如,如果您正在读取包含4个字符代码、浮点数和字符串的二进制数据,则应将4个字符代码读入4字节数组及浮点数中。我将读取字符串的长度,然后创建一个缓冲区以一次性读取整个字符串数据块。
如果您正在进行流式数据处理,则应查看BinaryReader和BinaryWriter类。它们使您可以轻松处理二进制数据,而无需过多关注数据本身。它还允许您将缓冲区大小与实际正在处理的数据分离开来。您可以在底层流上设置一个16k缓冲区,并使用BinaryReader轻松读取单个数据值。

感谢您建议使用BinaryReader。使用BinaryReader有助于读取字符串,因为我不需要编写代码来写入长度。我将测试8K和16K的读取,以查看性能是否提高。个人而言,我不在意大小,但是一些QA人员想要看看我们是否可以通过更好地利用硬件和操作系统来改善性能。 - Andrew Keith
如果你只是将大量数据流式传输到内存中,那么你可以尝试使用更大的缓冲区。只要保持缓冲区大小为磁盘簇大小的倍数,就应该是最优的。老实说,我认为我仍然深深地根植于我在90年代末和2000年代初的旧做法。如果你运行这个程序的系统是现代化和高性能的,32k、64k甚至更大的缓冲区可能会有帮助。如果你太大了(比如1mb),你可能会看到收益递减,因为其他因素开始发挥作用(比如交换抖动)。关键是匹配读取低级行为。 - jrista

4
取决于您在访问时间和内存使用之间划分线的位置。缓冲区越大,速度越快 - 但在内存方面更昂贵。以文件系统簇大小的倍数阅读可能是最有效的,在使用NTFS的Windows XP系统中,4K是默认的簇大小。您可以查看此链接:NTFS、FAT和exFAT的默认簇大小。再见。

我将尝试@jrista建议的8K和16K读取。有趣的是,文章说Windows在16 TB磁盘分区中使用8k簇。我以前从未见过如此大的分区。 - Andrew Keith
1
安德鲁,8K和16K是4K的倍数。 - RRUZ
1
旧硬盘一次读写整个512字节扇区。现代硬盘一次读写整个4096字节扇区。Windows NTFS默认的簇大小为4096字节。使用Windows事件跟踪,您可以看到Windows最常实际进行硬盘I/O的大小为16,384字节,以及4,096字节(较少的是819249152字节)。理想情况下,保持为4k的倍数,即16384字节。 - Ian Boyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接