Jab*_*bba 48 c++ performance printf cout
在进行了一些测试后,我发现它printf比它快得多cout.我知道它依赖于实现,但在我的Linux机器上printf速度提高了8倍.所以我的想法是混合两种打印方法:我想cout用于简单的打印,我打算printf用于生成大量输出(通常在循环中).只要在切换到其他方法之前不忘记刷新,我认为这样做是安全的:
cout << "Hello" << endl;
cout.flush();
for (int i=0; i<1000000; ++i) {
printf("World!\n");
}
fflush(stdout);
cout << "last line" << endl;
cout << flush;
Run Code Online (Sandbox Code Playgroud)
这样好吗?
更新:感谢所有宝贵的反馈.答案摘要:如果你想避免棘手的解决方案,只需简单地不使用endl,cout因为它会隐式刷新缓冲区.请"\n"改用.如果你产生大量输出会很有趣.
Jer*_*fin 69
直接的答案是肯定的,没关系.
很多人都围绕着如何提高速度的各种想法,但似乎有很多分歧是最有效的.我决定写一个快速测试程序,以至少了解哪些技术做了什么.
#include <iostream>
#include <string>
#include <sstream>
#include <time.h>
#include <iomanip>
#include <algorithm>
#include <iterator>
#include <stdio.h>
char fmt[] = "%s\n";
static const int count = 3000000;
static char const *const string = "This is a string.";
static std::string s = std::string(string) + "\n";
void show_time(void (*f)(), char const *caption) {
clock_t start = clock();
f();
clock_t ticks = clock()-start;
std::cerr << std::setw(30) << caption
<< ": "
<< (double)ticks/CLOCKS_PER_SEC << "\n";
}
void use_printf() {
for (int i=0; i<count; i++)
printf(fmt, string);
}
void use_puts() {
for (int i=0; i<count; i++)
puts(string);
}
void use_cout() {
for (int i=0; i<count; i++)
std::cout << string << "\n";
}
void use_cout_unsync() {
std::cout.sync_with_stdio(false);
for (int i=0; i<count; i++)
std::cout << string << "\n";
std::cout.sync_with_stdio(true);
}
void use_stringstream() {
std::stringstream temp;
for (int i=0; i<count; i++)
temp << string << "\n";
std::cout << temp.str();
}
void use_endl() {
for (int i=0; i<count; i++)
std::cout << string << std::endl;
}
void use_fill_n() {
std::fill_n(std::ostream_iterator<char const *>(std::cout, "\n"), count, string);
}
void use_write() {
for (int i = 0; i < count; i++)
std::cout.write(s.data(), s.size());
}
int main() {
show_time(use_printf, "Time using printf");
show_time(use_puts, "Time using puts");
show_time(use_cout, "Time using cout (synced)");
show_time(use_cout_unsync, "Time using cout (un-synced)");
show_time(use_stringstream, "Time using stringstream");
show_time(use_endl, "Time using endl");
show_time(use_fill_n, "Time using fill_n");
show_time(use_write, "Time using write");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在使用VC++ 2013(x86和x64版本)进行编译后,我在Windows上运行了这个.一次运行的输出(输出重定向到磁盘文件)如下所示:
Time using printf: 0.953
Time using puts: 0.567
Time using cout (synced): 0.736
Time using cout (un-synced): 0.714
Time using stringstream: 0.725
Time using endl: 20.097
Time using fill_n: 0.749
Time using write: 0.499
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,结果各不相同,但我发现有一些有趣的观点:
我最近编辑了代码来强制拨打电话printf.Anders Kaseorg非常友好地指出 - 它g++识别特定的序列printf("%s\n", foo);相当于puts(foo);,并相应地生成代码(即生成代码来puts代替printf).将格式字符串移动到全局数组,并将其作为格式字符串传递产生相同的输出,但强制它通过printf而不是生成puts.当然,它们有可能在某一天左右进行优化,但至少现在(g ++ 5.1)测试g++ -O3 -S确认它实际上正在调用printf(前一个代码编译为调用的地方puts).
小智 19
发送std::endl到流附加a newline并刷新流.随后的调用cout.flush()是多余的.如果这是在时间cout与时间printf比较完成时你没有比较苹果和苹果.
Mar*_*ork 12
另请注意,C++流已同步到C流.
因此,它需要额外的工作才能保持同步.
另外需要注意的是确保冲洗流量相等.如果你在一个系统上连续冲洗流而不是另一个系统,那肯定会影响测试的速度.
在假设一个比另一个更快之前你应该:
您可以printf通过增加缓冲区大小来进一步提高性能stdout:
setvbuf (stdout, NULL, _IOFBF, 32768); // any value larger than 512 and also a
// a multiple of the system i/o buffer size is an improvement
Run Code Online (Sandbox Code Playgroud)
对操作系统执行i/o的调用次数几乎总是最昂贵的组件和性能限制器.
当然,如果cout输出混合stdout,则缓冲区刷新失败的目的是增加缓冲区大小.
您可以sync_with_stdio用来使C ++ IO更快。
cout.sync_with_stdio(false);
Run Code Online (Sandbox Code Playgroud)
应该提高您的输出性能cout。