我正在从文件中读取大约300万行并将它们插入到STL地图中。所以,在我的while循环中,我从文件中读取每一行,我还打印通过一个简单的cout语句来控制它是什么行号。我的一位朋友最近指出,这会使代码变慢。我想知道这是否属实,是不是为什么?
答案 0 :(得分:6)
如前所述,写入终端几乎肯定会变慢。为什么呢?
默认情况下,写入终端使用line buffering
*。这意味着缓冲区的内容每次传输遇到换行符。写入文件时,仅在缓冲区已满或手动刷新流时才刷新缓冲区。这是造成差异的主要原因,因为I / O操作的数量明显不同。
*:这适用于Unix实现,但其他实现可能没有缓冲(请参阅注释中的讨论)。
当您写入终端时,这涉及在屏幕上呈现,并且根据终端可能涉及其他可能降低程序速度的操作(并非所有终端都相同,您可能会发现速度上的显着差异切换到另一个)。
答案 1 :(得分:6)
如前所述,写入终端几乎肯定会变慢。为什么呢?
取决于您的操作系统,std::cout
可能会使用线路缓冲 - 这意味着每条线路可能会分别发送到终端程序。当您使用std::endl
而不是'\ n'时,它肯定会刷新缓冲区。以较小的块编写数据意味着额外的系统调用和渲染工作会大大减慢速度。
某些操作系统/编译器甚至更慢 - 例如,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页内容永远不会出现在屏幕上:可以是好又快。仍然,“跳跃滚动”并不总是被使用或想要,因为它意味着输出永远不会呈现给最终用户的眼睛:也许该程序在某些情况下打印出一个巨大的红色错误消息 - 跳跃滚动甚至不会为了引起用户的注意,它是一个闪烁,但没有跳转滚动,你可能会注意到它。
当我在Bloomberg工作时,我们有一个不断的日志文件更新流占用几个监视器 - 有时显示的输出会落后几分钟;从默认的Solaris xterm切换到rxvt确保它始终保持步调
将输出重定向到/ dev / null是查看特定终端减慢速度的好方法
答案 2 :(得分:4)
几乎可以肯定。写入终端是因为放慢速度而臭名昭着的。运行程序并将输出重定向到文件,看看它的速度有多快。然后完全取出输出语句并再次测量。你会立即看到这种行为。
这是一个脑死亡的例子:
#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倍。那是非常少量的印刷品!