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

标签 c io posix bufferstrategy

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

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

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

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

sh: ./codec: Bad file number

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

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

提前致谢。

最佳答案

我一直在思考同样的问题,我得出了一个非常简单的结论:

使用保守的默认值或启发式算法,但如果用户愿意,可以轻松覆盖它。

您知道,在某些情况下,用户可能不希望您的实用程序达到最大吞吐量,但可能会在后台执行任何操作。也许任务并不那么重要。就个人而言,在 Linux 中,我经常使用 niceionice 实用程序将长期但不优先的任务放在次要位置,可以这么说,这样它们就不会不要干扰我的实际工作。

过去十年的基准表明 128k 到 2M 的 block 大小(217 到 221 字节)始终如一地工作良好——几乎在所有方面都离最佳速率不远情况 - 平均值缓慢地向该范围的较大端移动。通常情况下,2 的幂大小似乎比非 2 的幂更好,尽管我还没有看到足够多的各种 RAID 配置基准来完全相信这一点。

因为您的实用程序几乎肯定会针对每个新的硬件类型/生成重新编译,所以我更愿意有一个默认的 block 大小,在编译时定义,但在运行时简单地覆盖它(通过命令行选项、环境变量和/或配置文件)。

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

(服务器和高性能计算(这是我思考过的地方), block 大小基本上是根据确切的硬件和工作负载进行基准测试,或者只是一个勉强的猜测。通常是后者.)

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

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

关于c - 如何确定每次读取系统调用要读取的合理字节数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35542188/

相关文章:

python 嵌入 C : define the python script as a C string?

c - 函数可以返回值,但不能返回没有指针变量的地址

c - 识别位图中设置的位并将其打印在字符串中

network-programming - 多线程应用程序中的直接内存访问 (DMA) 调度

c++ - 如何轮询 SSL BIO 对象?

c++ - C/C++ 中数据类型名称的含义

java - 在base64的javamail中附加大文件

c - 什么是 __dirstream,我们在哪里可以找到定义

c - 将数据提供给需要文件名的 C API

chdir 在 c 中不起作用