Fla*_*ius 26 c performance glibc stdout linux-kernel
我有一个小的C程序来计算哈希值(哈希表).我希望代码看起来很干净,但有一些与它无关的东西让我烦恼.
我可以在大约0.2-0.3秒内轻松生成大约一百万个哈希值(以/ usr/bin/time为基准).但是,当我在forf循环中使用printf()时,程序会减慢到大约5秒钟.
我期待着有趣而详细的回复.谢谢.
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
您可以将字符串存储在缓冲区中,并在缓冲区已满时将它们输出到文件(或控制台)或定期输出.
如果输出到控制台,滚动通常是一个杀手.
如果你是printf()到控制台,它通常非常慢.我不确定为什么,但我相信它不会返回,直到控制台以图形方式显示输出的字符串.另外,你不能mmap()到stdout.
写入文件应该快得多(但仍然比计算散列慢几个数量级,所有I/O都很慢).
与直接计算相比,I/O总是很慢.系统必须等待更多组件可用才能使用它们.然后它必须等待响应才能继续.相反,如果它只是简单的计算,那么它只是真正在RAM和CPU寄存器之间移动数据.
我没有对此进行测试,但是将哈希附加到字符串上可能会更快,然后只需在末尾打印字符串.虽然如果你使用C而不是C++,这可能会很痛苦!
3和4超出我的恐惧.