混合cout和printf以获得更快的输出

执行一些testing后,我发现printfcout快得多。 我知道它是依赖于实现的,但在我的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; 

这样可以吗?

更新:感谢所有宝贵的反馈。 答案总结:如果你想避免棘手的解决scheme,只是简单地不要使用带有cout endl ,因为它隐式地刷新缓冲区。 改用"\n" 。 如果产生大量输出,这可能会很有趣。

直接的答案是,没关系。

很多人围绕如何提高速度提出了各种各样的想法,但是在哪个方面最为有效的问题似乎存在一些分歧。 我决定写一个快速的testing程序,至less弄清楚哪些技术做了什么。

 #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; } 

我使用VC ++ 2013(x86和x64版本)进行编译后,在Windows上运行了这个程序。 一次运行(输出redirect到磁盘文件)的输出如下所示:

  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 

正如预期的那样,结果会有所不同,但有几点我觉得很有趣:

  1. 写入NUL设备时,printf / puts比cout快得多
    • 但是在写入一个真实的文件时,cout保持得很好
  2. 不less提议的优化成果很less
    • 在我的testing中,fill_n与其他任何东西一样快
  3. 到目前为止,最大的优化是避免endl
  4. cout.write给了最快的时间(虽然可能不是一个重大的边缘

我最近编辑了代码来强制调用printf 。 Anders Kaseorg非常友好地指出 – g++认识到特定的序列printf("%s\n", foo); 相当于puts(foo); ,并相应地生成代码(即生成代码来调用puts而不是printf )。 将格式string移动到全局数组中,并将格式string作为格式string传递,产生相同的输出,但强制通过printf而不是puts 。 当然,也有可能他们可能会在某一天对此进行优化,但至less现在(g ++ 5.1)用g++ -O3 -S了一个testing,确认它实际上调用了printf (前一个代码编译为puts的调用) 。

发送std::endl到stream附加一个newline并刷新stream。 随后调用cout.flush()是多余的。 如果这是在计时cout vs. printf时完成的,那么你并没有把苹果与苹果进行比较。

默认情况下,C和C ++标准输出stream是同步的,因此写入一个会导致另一个刷新,所以不需要显式刷新。

还要注意C ++stream同步到Cstream。
因此它做了额外的工作,以保持同步。

另外要注意的是要确保你冲洗stream等量。 如果连续冲洗一个系统而不是另一个会影响testing速度的系统。

在假定其中一个比另一个更快之前,你应该:

  • 来自CI / O的非同步C ++ I / O(请参阅sync_with_stdio())。
  • 确保冲洗量相当。

您可以通过增加stdout的缓冲区大小来进一步提高printf的性能:

 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的次数几乎总是最昂贵的组件和性能限制器。

当然,如果cout输出与stdout混合在一起,那么缓冲区刷新失败了缓冲区大小增加的目的。

你可以使用sync_with_stdio来使C ++ IO更快。

 cout.sync_with_stdio(false); 

应该用cout提高你的输出性能。

不要担心printfcout之间的性能。 如果要获得性能,请将格式化的输出与非格式化的输出分开。

puts("Hello World\n")printf("%s", "Hellow World\n")(主要是由于格式化开销)。 一旦你从纯文本中分离出格式化,你可以做一些技巧:

 const char hello[] = "Hello World\n"; cout.write(hello, sizeof(hello) - sizeof('\0')); 

为了加速格式化输出,诀窍是将所有格式化为string,然后使用string(或缓冲区)的块输出:

 const unsigned int MAX_BUFFER_SIZE = 256; char buffer[MAX_BUFFER_SIZE]; sprintf(buffer, "%d times is a charm.\n", 5); unsigned int text_length = strlen(buffer) - sizeof('\0'); fwrite(buffer, 1, text_length, stdout); 

为了进一步提高程序的性能,减less输出量。 你输出的东西越less,你的程序就会越快。 副作用是你的可执行文件的大小也会缩小。

那么,我想不出有什么理由要真正使用cout。 有一个庞大的模板来做一些简单的事情是完全疯狂的。 此外,就像它被devise为input尽可能慢,并在打字<<<<,然后在中间input值,并得到类似的东西>variables名>>>在意外之后我再也不想这么做了。

更不用提的是,如果包含std命名空间,世界将最终崩溃,如果你不打字,那么你的打字负担就会变得更加荒谬。

不过我也不喜欢printf。 对我来说,解决办法是创build自己的具体类,然后调用任何io东西是必要的。 那么你可以用任何你想要的方式来实现简单的io,无论你想要什么样的实现,无论你想要什么格式,等等(一般来说你想要浮动总是一种方式,而不是无条件地格式化800种方式,所以把在格式化与每个电话是一个笑话)。

所以我input的东西都是dout +“这比”+ debugIoType +“的”+ cPlusPlusMethod +“更为理智。 DOUT ++;

但你可以拥有任何你想要的东西。 有了大量的文件,这也是令人惊讶的,这也提高了编译时间。

另外,混合使用C和C ++也没什么问题,只要做到这一点就可以了,如果你使用的是使用C的问题,那么可以肯定的是,混淆C和C ++。

混合C ++和C iomethods被我的C ++书籍FYI推荐。 我很确定C函数践踏了C ++预期的状态。