如何通过调整缓冲区大小来优化读写?

4
如何在标准C++/C++11(无POSIX函数)中优化std::ifstream和std::ofstream的读写速度?(1 <-由于有多个问题,这些数字标识不同的点)
我不确定缓冲区的作用,请问以下内容是否正确:
对于读取:文件的大部分预加载到内存中(因此缓冲区大小定义了该大部分的大小)(2)
对于写入:数据先写入内存,一旦缓冲区已满,则从内存传输到文件系统(3)
如何设置std::ifstream和std::ofstream的缓冲区大小?(4)
考虑到我要处理非常大的二进制文件(几十GB),并且文件系统通常最适合大量读写,我可以定义100MB之类的缓冲区大小吗?如果会降低性能,为什么?(5)
最后,是否默认缓冲区“智能”,即ifstream/ofstream将检测您要读取/写入文件的数据量,并调整缓冲区大小以提供最大速度?(6)

我不确定你是否正在寻找setvbuf()或其他内容。您能否澄清一下,自适应缓冲区是否可以解决您的问题? - Art Taylor
1
在Windows上使用VS 2010,对于写入std::ostream,性能峰值大约在64 KiB的缓冲区大小处。 - wilx
1个回答

7
你对缓冲区工作原理的描述是正确的。但是,缓冲区大小大于1MB可能不会带来任何好处。实际上,甜点可能远低于该值。请注意,std::ifstreamstd::ofstream使用的缓冲区与磁盘缓存无关 - 这是内核的工作,它会自行决定。流缓冲区仅影响一次系统调用中传输到内核或从内核传输的最大字节数。因此,理想的缓冲区大小并不取决于您传输的数据量。它取决于以下几点:
1. 系统调用的开销。开销越高,您就需要一次性传输更多的数据。 2. 缓冲区管理的开销。如果有的话,较大的缓冲区可能会导致较大的开销。 3. CPU缓存崩溃效应。将强烈支持较小的缓冲区。
由于(1)有利于较大的缓冲区,而(2)和(3)有利于较小的缓冲区,因此在某个地方会有一个甜点。由于CPU缓存大小可能约为几兆字节左右,接近该限制的缓冲区大小将受到(3)的严重影响,因此甜点肯定低于1MB左右。您可以忽略(2),因此仍需要估计(1)以获得缓冲区大小的下限。假设系统调用成本约为1000个周期左右,并假设CPU +内存的原始复制速度为4字节/周期。然后传输4k的成本大约相当于执行一个系统调用。因此,使用20k的缓冲区大小,系统调用开销大约为20%,而在使用100k的缓冲区大小时,它约为4%。因此,理想的缓冲区大小在几百kB的范围内独立于文件大小!除非分析提供了有关影响性能的缓冲区问题的硬证据,否则您可以相信标准库实现会正确处理这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接