如何确定每个读取系统调用要读取的合理字节数?

Dmi*_*try 3 c io posix bufferstrategy

我正在玩文件读/写,但很难决定为“读”系统调用设置多大的读缓冲区。

特别是,我正在查看“ http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html

除了 SSIZE_MAX 之外,它似乎没有说明我可以一次读取多少字节的任何限制。

更糟糕的是,如果我用 SSIZE_MAX 个字符创建一个数组,程序会产生一个:

sh: ./codec: Bad file number
Run Code Online (Sandbox Code Playgroud)

有没有合理的方法来决定每个读取系统调用读取多少字节?我担心这可能会因系统而异(我不能只进行尽可能多的读取,直到读取无法确定我可以读取的确切字节数,即使我这样做了,也不一定会更快比读取更少的字节)。

我的一个想法是检查我的 CPU 缓存大小并尝试使我的缓冲区不大于该大小,但由于我不知道 CPU 缓存如何工作,我不确定这是否一定正确。

提前致谢。

Nom*_*mal 5

我思考了基本相同的问题,得出了一个非常简单的结论:

使用保守的默认值或启发式方法,但让用户根据需要轻松覆盖它。

您会看到,在某些情况下,用户可能不希望您的实用程序获得最大吞吐量,但可能会在后台执行任何操作。也许这个任务并不那么重要。就个人而言,在Linux中,我经常使用niceionice公用事业把长但并非优先级的任务能拖就拖,可以这么说,让他们不与我的实际工作造成干扰。

过去十年中的基准测试表明 128k 到 2M 块大小(2 17到 2 21字节)始终运行良好——几乎在所有情况下都与最佳速率相距不远——平均缓慢地向该范围的较大端移动。通常,两种大小的幂似乎比非 2 的幂效果更好,尽管我还没有看到足够的各种 RAID 配置的基准测试来完全信任它。

因为您的实用程序几乎肯定会为每个新的硬件类型/代重新编译,所以我更喜欢在编译时定义的默认块大小,但在运行时对其进行简单的覆盖(通过命令行选项,环境变量,和/或配置文件)。

如果您的实用程序是为当前的 POSIXy 操作系统打包的,则二进制文件可以使用似乎最适合在该机器上完成的任务类型的默认值;例如,Raspberry Pis 和其他 SBC 开始时通常没有那么多内存,因此较小(例如 65536 字节)的默认块大小可能效果最佳。桌面用户可能不关心内存占用,因此您可以在当前桌面计算机上使用更大的默认块大小。

(服务器和高性能计算(这是我考虑过的地方),块大小基本上要么基于确切的硬件和工作负载进行基准测试,要么只是一个几乎不知情的猜测。通常是后者。)

或者,您可以根据所st_blksize涉及文件的s构造一个启发式方法,也许乘以一个默认因子,并限制在某个首选范围内。然而,随着硬件的变化,这种启发式方法往往会快速腐烂。

使用启发式方法时,重要的是要记住,其思想并不总是达到最佳状态,而是要避免真正糟糕的结果。如果用户想要挤出最后百分之几的性能,他们可以在自己的工作流程中进行一些基准测试,并相应地调整默认值。(我个人有,而且确实如此。)