printf减慢了我的程序

Fla*_*ius 26 c performance glibc stdout linux-kernel

我有一个小的C程序来计算哈希值(哈希表).我希望代码看起来很干净,但有一些与它无关的东西让我烦恼.

我可以在大约0.2-0.3秒内轻松生成大约一百万个哈希值(以/ usr/bin/time为基准).但是,当我在forf循环中使用printf()时,程序会减慢到大约5秒钟.

  1. 为什么是这样?
  2. 如何让它更快?mmapp()ing stdout也许?
  3. stdlibc是如何设计的,以及如何改进?
  4. 内核怎么能更好地支持它?如何修改本地"文件"(套接字,管道等)的吞吐量真的很快?

我期待着有趣而详细的回复.谢谢.

PS:这是一个编译器构造工具集,所以不要害羞进入细节.虽然这与问题本身无关,但我只想指出细节让我感兴趣.

附录

我正在寻找更多解决方案和解释的程序方法.确实,管道工作起了作用,但我无法控制"用户"的作用.

当然,我现在正在进行测试,"普通用户"不会这样做.但这并没有改变一个简单的printf()减慢一个进程的事实,这是我试图找到一个最佳的编程解决方案的问题.


附录 - 惊人的结果

参考时间用于TTY内的普通printf()调用,大约需要4分钟20秒.

在/ dev/pts(例如Konsole)下进行测试可将输出速度提高到约5秒.

在我的测试代码中使用setbuffer()大小为16384时需要大约相同的时间,对于8192几乎相同:大约6秒.

setbuffer()在使用时显然没有效果:它需要相同的时间(在TTY上大约4分钟,在PTS上大约5秒).

令人惊讶的是,如果我在TTY1上开始测试然后切换到另一个TTY,它确实需要与PTS相同:大约5秒.

结论:内核做了一些与可访问性和用户友好性有关的事情.呵呵!

通常情况下,无论你是在活动时盯着TTY还是切换到另一个TTY,它都应该同样慢.


课程:运行输出密集型程序时,切换到另一个TTY!

qrd*_*rdl 32

无缓冲输出非常慢.

默认情况下stdout是完全缓冲的,但是当连接到终端时,stdout要么是无缓冲的,要么是行缓冲的.

尝试打开缓冲stdout使用setvbuf(),如下所示:

char buffer[8192];

setvbuf(stdout, buffer, _IOFBF, sizeof(buffer));
Run Code Online (Sandbox Code Playgroud)


edo*_*lin 14

您可以将字符串存储在缓冲区中,并在缓冲区已满时将它们输出到文件(或控制台)或定期输出.

如果输出到控制台,滚动通常是一个杀手.

  • +1,特别是滚动.想象一下滚动中涉及的所有blitting和位图复制...... (4认同)
  • 您的回复让我在干净的TTY下以及Konsole的托管PTS下测试程序.结果:Konsole加快了速度!从TTY运行时需要4分20秒(我认为应该用作测试的真正参考),距离PTY 5秒. (2认同)

Tho*_*ini 9

如果你是printf()到控制台,它通常非常慢.我不确定为什么,但我相信它不会返回,直到控制台以图形方式显示输出的字符串.另外,你不能mmap()到stdout.

写入文件应该快得多(但仍然比计算散列慢几个数量级,所有I/O都很慢).


cor*_*vus 7

您可以尝试将shell中的输出从控制台重定向到文件.使用此功能,可以在几秒钟内创建大小为千兆字节的日志.


n00*_*dle 6

  1. 与直接计算相比,I/O总是很慢.系统必须等待更多组件可用才能使用它们.然后它必须等待响应才能继续.相反,如果它只是简单的计算,那么它只是真正在RAM和CPU寄存器之间移动数据.

  2. 我没有对此进行测试,但是将哈希附加到字符串上可能会更快,然后只需在末尾打印字符串.虽然如果你使用C而不是C++,这可能会很痛苦!

3和4超出我的恐惧.