【问题标题】:How to decide a buffer's size如何确定缓冲区的大小
【发布时间】:2017-04-04 05:46:39
【问题描述】:

我有一个程序,它的目的是从一些输入文本文件中读取,将所有可打印的字符(即 32 到 126 之间的 ASCII)过滤到一些其他输出文本文件中。

我还得到一个参数“DataAmount”——这意味着我需要读取的数据量是多少——可能是 1B、1K、1M、1G、80000B 等(单位之前可以是任何自然数)。

这不是输入文件的大小,而是我需要从输入文件中读取多少。如果输入文件小于 DataAmount,我需要重新读取文件,直到我准确读取 DataAmount 字节。

对于过滤,我从输入文件读取到某个缓冲区。我从缓冲区过滤到其他缓冲区中的可打印字符,然后从该缓冲区写入输出文件(两个缓冲区大小相同)。

另一个问题是,我怎样才能确定这两个缓冲区的最佳大小,所以对 read() 和 write() 的调用最少?

(注意:我不会一次写入整个数据,因为它可能太大了,我不会一次写入每个字节。我仅在缓冲区为满)。

目前,我构建的缓冲区大小仅取决于单位:

如果是 B 或 K,大小为 1024。

如果是 M 或 G,则大小为 4096。

这一点都不好,因为对于 1B 和 100000B,我将拥有相同大小的缓冲区。

我该如何改进?

【问题讨论】:

  • 总是使用 4096 有什么问题?
  • @jxh 如果我的输入是 1B,那就太大了..
  • 我会选择 4096 字节。它是standard size of physical blocks on most machines nowadays,因此这将最大限度地减少您必须实际访问磁盘的次数。较小文件的开销完全可以忽略不计。
  • @ChikChak:那有什么问题?
  • 没有。除非您使用的是 RAM 受限的嵌入式控制器等,否则只需使用页面大小即可。

标签: c file malloc buffer


【解决方案1】:

我个人的经验是,只要您使用几 KB,缓冲区大小就无关紧要。

正如您在问题中指出的那样,执行系统调用会产生开销,因此一次执行一个字符的 I/O 效率并不高,您可以通过读取和写入更大的块来减少开销。但是,还有其他事情需要时间,任何合理的缓冲量都会将您的系统调用开销降低到其他事情花费大部分时间的程度。在这一点上,更大的缓冲区不会使程序明显更快。缓冲区太大也有问题,所以你也可能在那个方向上犯错。

我不会像您那样使缓冲区大小动态化。它在程序中引入了不必要的复杂性。您可以通过运行具有不同缓冲区大小的程序来验证这一点,看看它会产生什么样的差异。

至于要使用的实际值,stdio.h 头文件定义了宏 BUFSIZ,它是 stdio 缓冲区的默认大小。该宏的大小合理。

另外请注意,如果您使用 stdio 函数来执行 I/O,它们已经提供了缓冲(如果您不直接调用系统调用 read() 和 write(),那么您正在使用 stdio。)实际上没有理由将数据缓冲两次,因此您可以一次执行一个字符的 I/O 并让 stdio 缓冲区为您处理它,或者使用 setvbuf() 禁用 stdio 缓冲。

【讨论】:

    【解决方案2】:

    如果您之前知道输入,您可以对一些统计信息进行统计并获得平均值,因此它不是固定大小而是近似值。

    但我建议你:不要担心readclose 系统调用。如果您从输入中读取的数据非常少并且缓冲区很高,那么您会浪费一些字节。如果你得到一个大的输入并且有一个小的缓冲区,你只需要做一些额外的迭代。

    缓冲区大小适中。例如,512。

    【讨论】:

    • 是的,但我不想要任何额外的不必要的调用和读取。我需要对文件的影响最小化。
    • 然后您可以使用 args 传递的 DataAmount 值创建缓冲区。你有一个先验的缓冲区大小。
    【解决方案3】:

    一旦你决定了单位,然后决定单位的数量是否需要额外的缓冲区大小。因此,一旦您找到了 B,请检查该值。这样您就不必拆分较小的单元。

    您可以在单位指标上执行 switch 语句,然后根据该单位的数值在每种情况下进行处理。例如,对于 B 进行最大值的整数除法,并根据结果设置实际缓冲区大小(同样在 switch/case 序列中)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      相关资源
      最近更新 更多