什么是理想的缓冲区大小?

30
Possible Duplicate: 如何确定使用FileInputStream时的理想缓冲区大小?

从文件(或任何输入流)中读取原始数据时,使用C ++的 istream 系列的 read()或C的 fread(),必须提供一个缓冲区以及要读取的数据量。我见过的大多数程序似乎都是随意选择512到4096之间的2的幂。

  1. 为什么必须/应该是2的幂次方,还是程序员对2的自然倾向?
  2. 什么是“理想”的数字? 通过“理想”,我指的是速度最快的数字。 我假设它必须是基础设备缓冲区的倍数? 或者下层流对象的缓冲区? 我怎样才能确定那些缓冲区的大小呢? 一旦我这样做了,使用它的倍数会比使用exact size更快吗?

编辑
大多数答案似乎是在编译时无法确定。 我可以在运行时找到它。


我相信缓冲区大小取决于编译器或机器(抱歉,我不知道是哪个或者可能两者都有)。唯一的方法是通过读取各种数据大小来尝试。它应该很快,所以做100次并取平均值。它不应该是一条直线。我的猜测是你应该注意到当你越过需要读取另一个数据缓冲区的点时。 (或者,您可以查看C/C++的源代码...) - Ray
14
如果有疑问,始终将缓冲区大小设为2的幂次方。其他程序员会认为你这样做是出于一些聪明的原因。;-) - Frerich Raabe
重新编辑:运行时间并没有太大帮助。除非你能负担得起每次启动自适应缓冲代码时进行大量数据的极端“热身运行”,否则你需要在开发时进行分析,以便进行性能优化。 - Jirka Hanika
6个回答

23

SOURCE:
如何确定使用FileInputStream时的理想缓冲区大小?

理想缓冲区大小与很多因素有关:文件系统块大小、CPU缓存大小和缓存延迟。

大多数文件系统都配置为使用4096或8192字节的块大小。从理论上讲,如果你配置缓冲区大小,使得你读取的字节数比磁盘块多一点,那么文件系统的操作可能会非常低效(例如,如果你将缓冲区配置为每次读取4100字节,则每次读取都需要通过文件系统读取2个块)。如果这些块已经在缓存中,那么你就要付出RAM -> L3/L2缓存延迟的代价。如果你运气不好而这些块尚未在缓存中,则你还要付出磁盘->RAM延迟的代价。

这就是为什么你看到大多数缓冲区大小都是2的幂,并且通常大于(或等于)磁盘块大小的原因。这意味着你的一个流读取可能会导致多个磁盘块读取 - 但是这些读取将始终使用完整的块,没有浪费的读取。

同时,这也通常会影响到其他对性能友好的参数,这些参数同时影响读取和后续处理:数据总线宽度对齐、DMA对齐、内存缓存行对齐、整数个虚拟内存页面。


4
  1. 至少在我的情况下,假设底层系统使用的缓冲区大小也是2的幂,因此最好尝试匹配。我认为现在缓冲区应该比“大多数”程序员倾向于制作的缓冲区稍微大一些。例如,我会选择32 KB而不是4。
  2. 不幸的是,很难事先知道。它取决于您的应用程序是I/O绑定还是CPU绑定,例如。

我不需要提前准备。在运行时找到它对我来说就可以了。 - Baruch

1
我认为大多数情况下只是选择一个“圆”数。如果计算机使用十进制,我们可能会选择1000或10000而不是1024或8192。没有非常好的理由。
一个可能的原因是磁盘扇区通常是512字节大小,因此读取其倍数更有效,假设所有硬件层和缓存使得低级代码实际上能够高效地利用这个事实。除非你正在编写设备驱动程序或进行无缓冲读取,否则它可能无法做到这一点。

0

我不知道为什么它必须是2的幂次方。你受到缓冲区大小必须在最大size_t范围内的限制,但这不太可能成为问题。

显然,缓冲区越大越好,但这显然不可扩展,因此必须考虑系统资源考虑因素,无论是在编译时还是最好在运行时。


0
1. 这必须/应该是2的幂次方,还是程序员对2的幂次方有自然倾向?

并没有。它应该是一些能够适应数据总线宽度大小的东西,以简化内存复制,因此任何可以被16整除的东西都可以使用当前技术。使用2的幂次方使得它很可能在未来的技术中也能很好地工作。
2. “理想”的数字是多少?通过“理想”,我指的是速度最快的。

速度最快的是尽可能多的使用内存。但是,一旦超过几千字节,与使用的内存量相比,你将会有非常小的性能差异。
我假设它必须是底层设备缓冲区的倍数?或者底层流对象的缓冲区?无论如何,我怎样才能确定这些缓冲区的大小?
你实际上无法知道底层缓冲区的大小,也不能依赖于它们保持不变。
一旦我知道了,使用它的倍数是否比仅使用确切大小更快?

一些,但非常少。


0

我认为缓冲区的理想大小应该是硬盘中一个块的大小,这样在从硬盘存储或获取数据时可以正确地映射到缓冲区。


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