缓冲区刷新:"\n" vs. std::endl

30 浏览
0 Comments

缓冲区刷新:"\n" vs. std::endl

在《Accelerated C++》中提到了两件事情:\n

    \n

  1. 大多数系统在将字符写入输出设备时需要花费相当长的时间。因此,C++会将要写入的字符累积到一个缓冲区中,并等待缓冲区被刷新。
  2. \n

  3. 缓冲区可以通过使用std::endl来显式地刷新。
  4. \n

\n这让我想知道:显然,除了最大的输出之外,使用\"\\n\"和使用std::endl的好处会非常小且不可察觉,但是使用\"\\n\"比使用std::endl更快,还是\"\\n\"也会刷新缓冲区?

0
0 Comments

在第三方库中,向流中写入'\n'的含义可能与写入std::endl/std::flush不同。例如,在当前项目中,我正在使用基于ostream的日志记录器。该记录器使用std::stringstream的功能进行输出格式化,但是已经重写了用于刷新的操作符。这样可以在日志中写入'\n'而不进行刷新,从而简化了代码。

以下是一个伪代码示例:

class MyStream
{
    // [cut]
    std::stringstream m_buffer;
    // [cut]
};
// friends:
template 
MyStream& operator<<(MyStream& stream, const Printable& value)
{
     stream.m_buffer << value;
}
typedef decltype(std::flush) TManipulator;
template <>
MyStream& operator<<(MyStream& stream, const TManipulator& manipulator)
{
     if ( manipulator == std::flush || manipulator == std::endl )
         stream.sendLogLine();
     else
         stream.m_buffer << manipulator;
}
// usage sample
void main()
{
    getLoggerStream() << "hello" << std::endl;
}

P.S. 我不喜欢子类化std::stringstream,所以MyStream是一个适配器。如果我想要使'\n'刷新,我应该重新实现更多功能,包括char*、std::string和其他特化类型。

0
0 Comments

使用'\n'不会刷新缓冲区,相比使用std::endl确实更快。

在典型的I/O中,在写入到目标设备之前会对输出进行缓冲。这样,当写入到访问速度较慢的设备(如文件)时,不需要在每个字符后都访问设备。刷新操作会将缓冲区"刷新"到设备上,从而导致明显的性能开销。

对于一些[一般来说]非常小的"faster"值来说 😉

:好吧,当向文件输出大量数据时,它实际上可能会降低性能(当我在CSV中写入数十兆字节的数据时,我曾经遇到过这种情况)。

确实,我没有考虑到这个反向情况 🙁

:另一方面,iostream不是输出内容的最快方式,所以还会有其他许多因素对性能产生负面影响。

:iostream的设计非常糟糕,但在g++实现中,我发现它在某些情况下稍微比C stdio快一点。

0