例如,请参阅以下代码。 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;
}
答案 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,但读取或写入将是顺序的(在理想情况下)。