4

如何在标准 C++/C++11(无 POSIX 函数)中优化 std::ifstream 和 std::ofstream 的读写速度?(1 <- 因为有几个问题,这些数字表示不同的点)

我不确切知道缓冲区的作用,所以你能确认一下:

  • 用于读取:文件的很大一部分预加载在内存中(因此缓冲区大小定义了这一大部分的大小)(2)
  • 用于写入:数据写入内存,一旦缓冲区满,就会从内存传输到文件系统 (3)

如何在 std::ifstream 和 std::ofstream 上设置缓冲区大小?(4)

考虑到我使用非常大的二进制文件(几个 10 GB),并且文件系统通常最适合大型读/写,我可以定义一个 100 MB 的缓冲区大小吗?如果它会降低性能,为什么?(5)

最后,从 ifstream/ofstream 将检测您正在读取/写入文件的数据量并调整缓冲区大小以提供最大速度的意义上说,默认缓冲区是否“智能”?(6)

4

1 回答 1

7

AFAICS,您对缓冲工作原理的描述是正确的。

但是,大于 1 MB 的缓冲区不太可能给您带来任何好处。实际上,甜蜜点可能远低于该值。请注意,缓冲区使用的缓冲区std::ifstreamstd::ofstream磁盘缓存无关——这是内核的工作,它自行决定。流缓冲区仅影响通过一个系统调用传入或传出内核的最大字节数。因此,理想的缓冲区大小并不取决于您传输的数据量。什么取决于是

  1. 系统调用的开销成本。更高的开销意味着您需要一次性传输更多数据。
  2. 缓冲区管理的间接成本。如果有的话,对于更大的缓冲区可能更大。
  3. CPU 缓存破坏效果。将强烈支持较小的缓冲区。

由于 (1) 有利于较大的缓冲区,而 (2) 和 (3) 有利于较小的缓冲区,因此在某个地方会有一个甜蜜点。由于 CPU 缓存大小可能是几兆字节左右,接近该限制的缓冲区大小将受到 (3) 的严重影响,因此最佳位置肯定在 1 MB 左右。您可能可以忽略 (2),因此仍然需要估计 (1) 以获得缓冲区大小的下限。假设一个系统调用大约需要 1000 个周期左右,并假设 CPU+内存的原始复制速度是 4 字节/周期。然后,传输 4k 的成本与进行一次系统调用的成本差不多。因此,缓冲区大小为 20k 时,系统调用开销大​​约为 20%,而缓冲区大小为 100k 时,系统调用开销约为 4%。因此,理想的缓冲区大小在几百 kB 的范围内与文件大小无关!

您可能可以相信您的标准库实现可以做到这一点,除非分析为您提供确凿的证据表明存在影响性能的缓冲问题

于 2012-10-06T10:35:02.660 回答