read/write 小数据性能有问题吗?

Is read/write small size of data performance problematic?

我正在使用 read/write 到 read/write from/to 本地磁盘常规文件。

我要read/write少量数据。例如

read(fd, buf, 15)
write(fd, buf, 39);

有人告诉我,当有人审查我的拉取请求时,我应该避免少量数据 read/write。

他们说:比如我应该分配一块4k这样的大内存,先把小数据拷贝到大内存中,一次写大内存,而不是多次写小数据。 而且我也应该读一次像4k的数据,然后把它存到大内存中,然后我就可以使用那个大内存了。

但我知道当我写小数据时,我写到页面缓存(?)所以内核会处理内存?当它足够大时,内核会写入磁盘吗?

我理解的对吗?我应该避免 read/write 小数据吗?

Is read/write small size of data performance problematic?

如果你只需要read/write少量数据,reading/writing更多是浪费时间。

如果你需要read/write大量的数据,reading/writing很多小块意味着你付出了多次在user-space和内核之间切换的开销(不管是否它是由内核 API 调用引起的切换或由页面错误等原因引起的切换)。这是否有问题取决于场景 - 例如对于只打算执行 3 次的粗略原型来说,它是无关紧要的,但对于在 IO 上花费大量时间的 high-performance 生产软件来说,它可能是不可取的(尤其是现在 Spectre 和 Meltdown 缓解措施增加了切换成本,并且特别是如果没有其他原因,比如 "code maintenance",这证明额外的开销是合理的)。

Am I understand right? Should I avoid read/write small data?

你想的对不对,小数据没必要回避read/write

I/O 子系统已经提供了 BUFSIZ 字节的读取缓冲区(Linux 上为 8192 字节,windows 上为 512 字节)(#define在过去的一年中在 glibc 中发生了变化,最初派生自 _IO_BUFSIZE,然后是 _LIO_BUFSIZ,现在在 glibc 源代码中只是 BUFSIZ

这是从 _IO_BUFSIZ 到普通 BUFSIZ Mechanically remove IO name aliases for types and constants (Wed, 7 Feb 2018).

的 glibc 提交

因此,无论您正在读取 one-byte 或 8192 字节(在 Linux 上)还是 512 字节(在 Windows 上)都没有关系没有任何性能损失。在您第一次请求时,I/O 缓冲区已经填充了 BUFSIZ 字节(或者如果文件包含少于 BUFSIZ 字节,则遇到 EOF 之前的字节数)来自文件的数据。所以你直接从内存中的 read-buffer 读取,小读取没有性能损失。

写入以类似的方式处理,直到 write-buffer 已满(或调用 syncfsfsync)才会写入磁盘,从而导致写入所有缓冲的文件数据到底层文件系统。