什么是最佳文件输出缓冲区大小?

时间:2015-08-23 23:57:11

标签: c++ c io buffer

例如,请参阅以下代码。 size是1MB,它肯定比1时运行得更快。我认为这是因为IO系统调用的数量减少了。这是否意味着我将永远受益于更大的缓冲区大小?我希望如此并进行一些测试,但似乎有一些限制。 size为2将比它为1时运行得快得多,但它不会更进一步。

有人可以更好地解释一下吗?可能的最佳缓冲区大小是多少?为什么我无法从无限扩大其规模中受益匪浅。

顺便说一句,在这个例子中,为了简单起见,我写信给stdout,但我也在考虑写入磁盘中的文件。

enum
{
  size = 1 << 20
};

void fill_buffer(char (*)[size]);

int main(void)
{
  long n = 100000000;
  for (;;)
  {
    char buf[size];
    fill_buffer(&buf);
    if (n <= size)
    {
      if (fwrite(buf, 1, n, stdout) != n)
      {
        goto error;
      }
      break;
    }
    if (fwrite(buf, 1, size, stdout) != size)
    {
      goto error;
    }
    n -= size;
  }
  return EXIT_SUCCESS;
error:
  fprintf(stderr, "fwrite failed\n");
  return EXIT_FAILURE;
}

2 个答案:

答案 0 :(得分:2)

您通常不需要最佳缓冲区大小,这可能需要查询操作系统的系统参数,并对目标环境进行复杂的估算甚至基准测试,并且它是动态的。幸运的是,您只需要一个足够好的值

我想说4K~16K缓冲器适合大多数正常使用。 4K是普通机器(x86,arm)支持的页面大小的神奇数字,也是普通物理磁盘扇区大小(512B或4K)的倍数。

如果您正在处理大量数据(千兆字节),您可能会发现简单的fwrite模型不适合其阻塞性质。

答案 1 :(得分:1)

在大型分区上,群集大小通常为32 KB。在大的读/写请求中,如果系统发现存在一系列连续的簇,则它们将它们组合成单个I / O.否则,它会将请求分解为多个I / O.我不知道最大I / O大小是多少。在某些旧的SCSI控制器上,它是64 KB或1 MB - 8 KB(17或255个描述符,在控制器中)。对于IDE / Sata,我已经能够为2 MB做IOCTL,确认它是带有外部总线监视器的单个I / O,但我从未测试过确定限制。

对于k方式自下而上的合并排序与k&gt;的外部排序如图2所示,读/写大小为10 MB到100 MB用于减少随机访问开销。请求将被分解为多个I / O,但读取或写入将是顺序的(在理想情况下)。