【问题标题】:What is the optimal file output buffer size?最佳文件输出缓冲区大小是多少?
【发布时间】:2015-08-23 23:57:11
【问题描述】:

请参见下面的代码示例。 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;
}

【问题讨论】:

  • 最佳输出缓冲区大小为:42。
  • 这太宽泛了...
  • 大小为 1 时,所涉及的系统调用的开销相对较高。随着更大的大小,系统调用开销的百分比会下降,并且“真实”写入文件系统缓存会占用运行时。我会写尽可能大的包。
  • 没有“最佳”。这取决于磁盘、操作系统、您可以腾出多少内存……随着您的增加,收益会递减。在某个时候,下一次增加的边际价值足够小,以至于您不想为此付出代价。测试和测量。
  • 在类 UNIX 操作系统上,您可以通过调用stat() 并查看st_blksize() 成员来找到给定文件的最佳缓冲区大小。如果这太乏味你也可以使用&lt;stdio.h&gt; 提供的BUFSIZ 宏作为一个很好的默认缓冲区大小。

标签: c++ c io buffer


【解决方案1】:

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

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

如果您正在处理大量数据(千兆字节),您可能会意识到简单的 fwrite-model 无法满足其阻塞特性。

【讨论】:

    【解决方案2】:

    在大分区上,簇大小通常为 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 > 2 的合并排序,使用 10 MB 到 100 MB 的读/写大小来减少随机访问开销。请求将被分解为多个 I/O,但读取或写入将是顺序的(在理想情况下)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-12
      • 1970-01-01
      • 2013-11-02
      • 2010-12-05
      • 1970-01-01
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      相关资源
      最近更新 更多