【问题标题】:Is read/write small size of data performance problematic?读/写小数据性能有问题吗?
【发布时间】:2019-10-23 12:30:54
【问题描述】:

我正在使用读/写来读取/写入本地磁盘常规文件。

我必须读/写少量数据。例如

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

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

他们说:比如我应该分配一个4k这样的大内存,先把小数据复制到大内存中,大内存写一次,而不是多次写小数据。 而且我也应该像4k数据一样读取一次,并将其存储到大内存中,然后我可以使用那个大内存。

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

我理解对了吗?我应该避免读/写小数据吗?

【问题讨论】:

  • "例如,我应该分配一个像 4k 这样的大内存" --> 不,底层 I/O 系统已经在这样做了。代码清晰。关注整体代码结构和性能,而不是小问题。
  • @chux 对于像 fread()fwrite() 这样的 C 标准库函数是这样,而不是像 read()write() 这样的基于 POSIX 系统调用的 I/O。
  • 您有什么理由使用read 而不是fread?后者会为你做缓冲。
  • 如果您正在处理的项目对 IO 性能有要求,您应该针对这些要求进行测试。只有当您的代码不符合要求时才考虑优化。如果项目没有要求,请使用最简单的代码来表达您的意图。

标签: c linux disk


【解决方案1】:

我理解对了吗?我应该避免读/写小数据吗?

你的想法是对的,不,没有必要避免读取/写入小数据。

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 提交

因此,无论您是读取 1 字节还是 8192 字节(在 Linux 上)还是 512 字节(在 Windows 上),都没有任何性能损失。在您第一次从文件中请求数据时,I/O 缓冲区已被 BUFSIZ 字节填充(或者,如果文件包含少于 BUFSIZ 字节,则遇到 EOF 之前的字节数)。因此,您直接从内存中的读取缓冲区读取,并且小读取不会影响性能。

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

【讨论】:

    【解决方案2】:

    读/写小数据性能有问题吗?

    如果你只需要读/写少量数据,读/写更多是浪费时间。

    如果你需要读/写大量数据,读/写很多小块意味着你付出了多次在用户空间和内核之间切换的开销(不管是内核API调用引起的切换还是由诸如页面错误之类的事情引起的切换)。这是否有问题取决于场景 - 例如对于只打算执行 3 次的粗略原型来说,这是无关紧要的,但对于在 IO 上花费大量时间的高性能生产软件来说,这可能是不可取的(尤其是现在有了 Spectre 和 Meltdown 缓解措施增加了切换成本,尤其是如果没有其他原因(例如“代码维护”)可以证明额外开销是合理的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-12
      • 1970-01-01
      • 2012-11-30
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 2017-09-06
      相关资源
      最近更新 更多