mixing cout and printf for faster output

c++, cout, performance, printf

Solution

The direct answer is that yes, that's okay.

A lot of people have thrown around various ideas of how to improve speed, but there seems to be quite a bit of disagreement over which is most effective. I decided to write a quick test program to get at least some idea of which techniques did what.

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

I ran this on Windows after compiling with VC++ 2013 (both x86 and x64 versions). Output from one run (with output redirected to a disk file) looked like this:

          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

As expected, results vary, but there are a few points I found interesting:

- printf/puts are much faster than cout when writing to the NUL device

- but cout keeps up quite nicely when writing to a real file

- Quite a few proposed optimizations accomplish little

- In my testing, fill_n is about as fast as anything else

- By far the biggest optimization is avoiding endl

- cout.write gave the fastest time (though probably not by a significant margin

I've recently edited the code to force a call to `printf`. Anders Kaseorg was kind enough to point out--that `g++` recognizes the specific sequence `printf("%s\n", foo);` is equivalent to `puts(foo);`, and generates code accordingly (i.e., generates code to call `puts` instead of `printf`). Moving the format string to a global array, and passing that as the format string produces identical output, but forces it to be produced via `printf` instead of `puts`. Of course, it's possible they might optimize around this some day as well, but at least for now (g++ 5.1) a test with `g++ -O3 -S` confirms that it's actually calling `printf` (where the previous code compiled to a call to `puts`).

Problem

After performing some tests I noticed that `printf` is much faster than `cout`. I know that it's implementation dependent, but on my Linux box `printf` is 8x faster. So my idea is to mix the two printing methods: I want to use `cout` for simple prints, and I plan to use `printf` for producing huge outputs (typically in a loop). I think it's safe to do as long as I don't forget to flush before switching to the other method: ``` cout << "Hello" << endl; cout.flush(); for (int i=0; i<1000000; ++i) { printf("World!\n"); } fflush(stdout); cout << "last line" << endl; cout << flush; ``` Is it OK like that? Update: Thanks for all the precious feedbacks. Summary of the answers: if you want to avoid tricky solutions, simply stick with `cout` but don't use `endl` since it flushes the buffer implicitly (slowing the process down). Use `"\n"` instead. It can be interesting if you produce large outputs.

Original source

Related problems