mixing cout and printf for faster output
在执行了一些测试之后,我注意到
1 2 3 4 5 6 7 8 9 10 11 | cout <<"Hello" << endl; cout.flush(); for (int i=0; i<1000000; ++i) { printf("World! "); } fflush(stdout); cout <<"last line" << endl; cout << flush; |
这样可以吗?
更新:感谢所有宝贵的反馈。答案总结:如果你想避免棘手的解决方案,就不要使用
"
直接的答案是,是的,没关系。
许多人对如何提高速度提出了各种各样的想法,但似乎对哪种方法最有效存在很大的分歧。我决定写一个快速测试程序,以至少了解哪些技术做了什么。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include <iostream> #include <string> #include <sstream> #include <time.h> #include <iomanip> #include #include <iterator> #include <stdio.h> char fmt[] ="%s "; static const int count = 3000000; static char const *const string ="This is a string."; static std::string s = std::string(string) +" "; 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 <<" "; } 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 <<" "; } void use_cout_unsync() { std::cout.sync_with_stdio(false); for (int i=0; i<count; i++) std::cout << string <<" "; std::cout.sync_with_stdio(true); } void use_stringstream() { std::stringstream temp; for (int i=0; i<count; i++) temp << string <<" "; 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," "), 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; } |
在用VC++2013(x86和x64版本)编译之后,我在Windows上运行了这个程序。一次运行的输出(将输出重定向到磁盘文件)如下所示:
1 2 3 4 5 6 7 8 | 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 |
正如预期的那样,结果各不相同,但我发现有几点很有趣:
- 但是在写真正的文件时不能很好地保持
- 在我的测试中,填充速度和其他任何东西一样快
我最近编辑了代码来强制调用
", foo);
发送
另外,注意C++流是同步到C流的。因此,保持同步需要额外的工作。
要注意的另一件事是确保冲洗流的量相等。如果您不断地冲洗一个系统上的流,而不是另一个系统,这肯定会影响测试的速度。
在假设其中一个比另一个快之前,您应该:
- 来自C I/O的非同步C++I/O(参见SycCyOffStdio-())。
- 确保冲洗量是可比的。
默认情况下,C和C++标准输出流是同步的,因此对一个输出流的写入会导致另一个流的刷新,因此不需要显式刷新。
通过增加
1 2 | 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 |
调用操作系统来执行I/O的次数几乎总是最昂贵的组件和性能限制。
当然,如果
你可以使用EDCOX1 5来更快地使C++ IO。
1 | cout.sync_with_stdio(false); |
应该用
不要担心
")
")
1 2 3 | const char hello[] ="Hello World "; cout.write(hello, sizeof(hello) - sizeof('\0')); |
为了加速格式化输出,技巧是对字符串执行所有格式化,然后将块输出与字符串(或缓冲区)一起使用:
1 2 3 4 5 6 | const unsigned int MAX_BUFFER_SIZE = 256; char buffer[MAX_BUFFER_SIZE]; sprintf(buffer,"%d times is a charm. ", 5); unsigned int text_length = strlen(buffer) - sizeof('\0'); fwrite(buffer, 1, text_length, stdout); |
为了进一步提高程序的性能,请减少输出量。你输出的东西越少,你的程序就越快。副作用是您的可执行文件大小也会缩小。
好吧,老实说,我想不出任何实际使用cout的理由。拥有一个庞大的模板来做一些如此简单的事情,将在每个文件中,这是完全疯狂的。另外,它的设计是尽可能慢地输入,并且在第一百万次输入<<<之后,在中间输入值,然后在意外事件中获得诸如>variablename>>之类的东西,我再也不想这样做了。
更不用说,如果您包含std名称空间,世界最终会内爆,如果您不包含,您的输入负担会变得更加荒谬。
不过,我也不太喜欢printf。对于我来说,解决方案是创建自己的具体类,然后调用其中所需的任何IO内容。然后,您可以以任何方式使用真正简单的IO,也可以使用您想要的任何实现、您想要的任何格式等(通常,您希望浮动始终是一种方式,例如,不要无缘无故地以800种方式对其进行格式化,所以每次调用都要进行格式化是一个笑话)。
所以我键入的是dout+"这比"+debugiotype+"的"+cplusplusMethod+"更理智。"IMO"至少";DOT++;
但你可以随心所欲。有了大量的文件,这也大大提高了编译时间。
此外,C和C++的混合并没有错,它应该公正地进行,如果你使用的是导致使用C的问题的东西,那么安全地说,至少你担心的是混合C和C++的麻烦。
我的C++书籍推荐FC++和C语言混合,FYI。我很确定C函数是在C++所期望的状态下进行的。