为什么ostringstream比ofstream更快

Bai*_*ang 10 c++ iostream filestream

要将许多数据写入文件,我有两种方法:

  1. 直接写入ofstream流

    ofstream file("c:\\test.txt");
    for (int i = 0; i < 10000; ++i)
    {
        file << data[i];
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 首先写入istringstream,然后立即写入ofstream

    ostringstream strstream;
    for (int i = 0; i < 10000; ++i)
    {
        strstream << data[i];
    }
    ofstream file("c:\\test.txt");
    file << strstream.str();
    
    Run Code Online (Sandbox Code Playgroud)

毫不奇怪,第二种方法更快,事实上,它比我的HP7800机器上的第一种方法快4倍.

但为什么?我知道ofstream正在使用filebuf,而ostringstream正在使用stringbuf - 作为缓冲区,它们都应该驻留在内存中,因此应该没有区别.

引擎盖下有什么区别?

sbi*_*sbi 17

你使用std::endl了很多而不是'\n'std::endl做两件事:它将一个'\n'插入到流中,然后将缓冲区刷新到磁盘.我已经看到代码通过这样做而谈到严重的性能损失.(在修复之后,代码运行速度提高了5-10倍.)
刷新到字符串缓冲区将比刷新到磁盘快得多,这样就可以解释您的发现.

如果不是这种情况,您可能会考虑增加缓冲区大小:

const std::size_t buf_size = 32768;
char my_buffer[buf_size];
ofstream file("c:\\test.txt");
file.rdbuf()->pubsetbuf(my_buffer, buf_size);

for (int i = 0; i < 10000; ++i)
{
    file << data[i];
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这是由于附加 **std::endl** 频繁刷新造成的。事实证明,当内存缓冲区大小不够时,filebuf 和 stringbuf 都可以增加其内存缓冲区大小。请参阅[此处](http://www.cplusplus.com/reference/iostream/filebuf/overflow/) (2认同)
  • @lzprgmr:1)所以我的第一个假设是正确的。好的。2) 流缓冲区通常___不会增长___其缓冲区,而是在溢出时___刷新到设备___。字符串流缓冲区是一个例外,因为它的“设备”___是___内存缓冲区(您可以从中获取字符串)。3) 当您对环境/设备有更多了解时可以使用`pubsetbuf()`。然后,您可以为流提供您认为合适的任何大小的缓冲区。我不确定除了提供 ___custom-sized___ 缓冲区之外是否还有其他用例。 (2认同)
  • 哇,从 endl 切换到“\n”速度有了巨大的提高,谢谢! (2认同)

Eri*_*rik 5

磁盘速度慢。许多小写比一个大写要贵。