C++:cout 语句是否会使代码变慢

C++: Does cout statement makes code slower

本文关键字:代码 是否 cout 语句 C++      更新时间:2023-10-16

我正在从文件中读取大约 300 万行并将它们插入到 STL 映射中。因此,在我的 while 循环中,我从文件中读取每一行,我还通过一个简单的 cout 语句打印到控制台它是什么行号。我的一位朋友最近指出,这会使代码变慢。我想知道这是否属实,如果是为什么?

如前所述,写入终端几乎肯定会变慢。为什么?

  • 根据您的操作系统,std::cout可能会使用线路缓冲 - 这意味着每条线路可能会单独发送到终端程序。 当您使用 std::endl 而不是 '' 时,它肯定会刷新缓冲区。 将数据写入较小的块意味着额外的系统调用和渲染工作,这会显着减慢速度。

  • 一些操作系统/编译器甚至更慢 - 例如,Visual C++:https://connect.microsoft.com/VisualStudio/feedback/details/642876/std-wcout-is-ten-times-slower-than-wprintf-performance-bug-in-c-library

  • 显示输出的终端需要调用以清除现有屏幕内容,渲染字体,更新滚动条,将行复制到历史记录/缓冲区中。 特别是当他们以小块的形式获得新内容时,他们无法可靠地猜测他们需要等待多长时间,并且可能会尝试更新屏幕以获取他们收到的一点点:这是昂贵的,也是过度刷新或无缓冲输出缓慢的原因。

    • 一些终端提供"跳转滚动"选项,这意味着如果他们发现他们落后 10 页,他们会立即渲染最后一页,而前 9 页的内容永远不会出现在屏幕上:这可能很好而且很快。 尽管如此,"跳转滚动"并不总是被使用或想要的,因为这意味着输出永远不会呈现给最终用户的眼睛:也许该程序在某些情况下是为了打印一个巨大的红色错误消息 - 使用跳转滚动甚至不会闪烁来吸引用户的注意力,但如果没有跳转滚动,您可能会注意到它。

    • 当我在彭博社工作时,我们有源源不断的日志文件更新,占用了几个显示器 - 有时显示的输出会落后几分钟;从默认的 Solaris xterm 切换到 rxvt 可确保它始终跟上步伐

  • 将输出重定向到/dev/null 是查看特定终端减慢速度的好方法

如前所述,写入终端几乎肯定会变慢。为什么?

  • 缓冲:

写入终端默认使用 line buffering *。这意味着每次遇到换行符时都会传输缓冲区的内容。写入文件时,仅当缓冲区已满或手动刷新流时,才会刷新缓冲区。这是造成差异的主要原因,因为 I/O 操作的数量明显不同。

*:对于Unix实现来说,这是正确的,但其他实现可能是无缓冲的(参见评论中的讨论)。

  • 渲染:

当您写入终端时,这涉及在屏幕上呈现,并且根据终端的不同,可能涉及其他操作,这些操作可能会减慢程序速度(并非所有终端都相同,您可能会发现速度显着差异只是切换到不同的终端)。

这几乎可以肯定是真的。 写信到终端是臭名昭著的减慢速度。 运行程序并将输出重定向到文件,看看它的速度有多快。 然后完全取出输出语句并再次测量。 您将立即看到该行为。

这是一个脑残的例子:

#include <stdio.h>
int main(void)
{
    int i;
    for (i = 0; i < 10000; i++)
    {
        printf("Hello, world!n");
    }
    return 0;
}

我构建了这个未优化的程序并运行了它,一次输出到终端,一次输出到文件。 终端输出的结果:

real 0m0.026s
user 0m0.003s
sys  0m0.007s

重定向 I/O 的结果:

real 0m0.003s
user 0m0.001s
sys  0m0.001s

你去吧,~8 倍快。 这是针对极少数印刷品!