15
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>

int main(int argc, char* argv[])
{
    std::clock_t start;
    double duration;    

    std::cout << "Starting std::cout test." << std::endl;
    start = std::clock();

    for (int i = 0; i < 1000; i++)
    {
        std::cout << "Hello, World! (" << i << ")" << std::endl;
    }

    duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;

    std::cout << "Ending std::cout test." << std::endl;
    std::cout << "Time taken: " << duration << std::endl;

    std::system("pause");

    std::cout << "Starting std::printf test." << std::endl;
    start = std::clock();

    for (int i = 0; i < 1000; i++)
    {
        std::printf("Hello, World! (%i)\n", i);
        std::fflush(stdout);
    }

    duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;

    std::cout << "Ending std::printf test." << std::endl;
    std::cout << "Time taken: " << duration << std::endl;

    system("pause");

    return 0;
}

Now, here are the times for the first five runs:

  • std::cout test: 1.125 s ; printf test: 0.195 s
  • std::cout test: 1.154 s ; printf test: 0.230 s
  • std::cout test: 1.142 s ; printf test: 0.216 s
  • std::cout test: 1.322 s ; printf test: 0.221 s
  • std::cout test: 1.108 s ; printf test: 0.232 s

As you can see, using printf and then fflushing takes about 5 times less time than using std::cout.

Although I did expect using std::cout's << operator to be perhaps a little slower (almost minimal) , I wasn't prepared for this huge difference. Am I making a fair test? If so, then what makes the first test so much slower than the second one, if they essentially do the exact same thing?

ApprenticeHacker
  • 21,351
  • 27
  • 103
  • 153
  • `std::endl` in every iteration is a bad idea. Use `'\n'`. They're not the same thing. – Nawaz Aug 20 '12 at 20:11
  • 2
    He did flush in the printf version too though, so that can't be it? – Cubic Aug 20 '12 at 20:12
  • 2
    The **possible duplicate** question does not answer my main question, `**what makes** the first test so much slower than the second one...` i.e _why_ exactly is the printf faster? – ApprenticeHacker Aug 20 '12 at 20:19
  • @ApprenticeHacker, it depends on realization: For me `cout` faster then `printf`, but only if I set `-std=c++0x`. – Lol4t0 Aug 20 '12 at 20:26
  • 1
    There may not be a single correct answer other than the quality of the library implementation you're using. There have been similar questions such as [this linked one](http://stackoverflow.com/questions/3643828/). Read it and the related questions it links to. – Blastfurnace Aug 20 '12 at 20:31
  • 3
    Note that `std::cout << "Hello, World! (" << i << ")" << std::endl;` is 4 function calls, while `printf` is only one. Try doing `printf` 5 times, like with `cout` and see what happens. Then you'll realize how much of the performance fail is due to function calls, and how much due the library itself. – Shahbaz Aug 20 '12 at 20:35
  • 2
    Your current timings are meaningless as the std::cout is synced with stdout and thus does a lot of "extra" work to maintain synchronization. If you decouple them you will see a speedup (it is still slower) `std::cout.sync_with_stdio(false);` – Martin York Aug 21 '12 at 15:34
  • 1
    It is quite unfair to flush `stdout` for each `printf`. Without the `std::fflush(stdout);` the `printf` loop executes much faster. While it is idiomatic to `<< std::endl`, it is not idiomatic to `fflush(stdout)`. Unsuspecting C++ programmers are likely to use `cout` much less inefficiently then `stdout` – chqrlie Dec 09 '15 at 19:47

6 Answers6

12

Try this:

#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <iostream>

int main(int argc, char* argv[])
{
#if defined(NOSYNC)
    std::cout.sync_with_stdio(false);
#endif

    std::cout << "Starting std::cout test." << std::endl;

    std::clock_t start = std::clock();

    for (int i = 0; i < 1000; i++)
    {   
        std::cout << "Hello, World! (" << i << ")" << std::endl;
    }   

    clock_t mid = std::clock();

    for (int i = 0; i < 1000; i++)
    {   
        std::printf("Hello, World! (%i)\n", i); 
        std::fflush(stdout);
    }   

    std::clock_t end = std::clock();

    std::cout << "Time taken: P1 " << ((mid-start)*1.0/CLOCKS_PER_SEC) << std::endl;

    std::cout << "Time taken: P2 " << ((end-mid)*1.0/CLOCKS_PER_SEC) << std::endl;


    return 0;
}

Then I get:

> g++ -O3 t13.cpp
> ./a.out
# lots of lines deleted
Time taken: P1 0.002517
Time taken: P2 0.001872

> g++ -O3 t13.cpp -DNOSYNC   
> ./a.out
# lots of lines deleted
Time taken: P1 0.002398
Time taken: P2 0.001878

So the P2 times do not change.
But you get an improvement of the P1 times (ie std::cout) using std::cout.sync_with_stdio(false);. Becuase the code no longer tries to keep the two stream (std::cout stdout) synchronized. Which if you are writing pure C++ and only using std::cout not a problem.

Martin York
  • 257,169
  • 86
  • 333
  • 562
10

For a true apples-to-apples comparison, re-write your test so that the only thing changing between the test cases is the print function being used:

int main(int argc, char* argv[])
{
    const char* teststring = "Test output string\n";
    std::clock_t start;
    double duration;

    std::cout << "Starting std::cout test." << std::endl;
    start = std::clock();

    for (int i = 0; i < 1000; i++)
        std::cout << teststring;
    /* Display timing results, code trimmed for brevity */

    for (int i = 0; i < 1000; i++) {
        std::printf(teststring);
        std::fflush(stdout);
    }
    /* Display timing results, code trimmed for brevity */
    return 0;
}

With that, you will be testing nothing but the differences between the printf and cout function calls. You won't incur any differences due to multiple << calls, etc. If you try this, I suspect that you'll get a much different result.

bta
  • 43,959
  • 6
  • 69
  • 99
  • Hmm, now it's only a difference of about 0.06 s. Guess that answers my question. – ApprenticeHacker Aug 20 '12 at 20:50
  • 6
    @bta, it seems to be an unfair test. For printf section you are flushing stdout after each iteration, but the std::cout code is not. Should probably add << std::flush(); to the std::cout section. – oz10 Aug 20 '12 at 21:06
  • 1
    Add the following: `std::cout.sync_with_stdio(false);` – Martin York Aug 20 '12 at 21:16
  • 3
    This is not a useful comparison if the performance difference between cout and printf is due to the formatting of the number i to a string. – joydeepb Oct 31 '13 at 18:46
  • @joydeepb- Probably not, but in this case my testing was showing that the multiple `<<` operators were the likely culprit so I didn't bother showing sample code that tested for other things. You could, however, apply the same general principle (eliminate variables to simplify the problem) to solve the problem if the int-to-string conversion was the culprit. – bta Nov 05 '13 at 00:40
  • 1
    If the difference is due to requiring many more `<<` calls than `printf` calls, it's totally appropriate to compare them that way. It's not realistic to simplify the test to the extent that you have. – Mark Ransom Sep 02 '16 at 15:16
4

use

cout << "\n";

to prevent buffering. much faster

Jason
  • 1,974
  • 24
  • 19
2

About 10 years ago, Scott Meyers tested the efficiency of iostream and scanf/printf. Depends on the compiler and environment, sometimes scanf/printf is 20% faster than iostream, sometimes even 200% faster. But iostream was never faster than scanf/printf. According to other two given examples, scanf/printf is still faster than iostream. However, Meyers said that "On a really useful program, there would be no differences." According to Google''s programming style([http://google-styleguide.googlecode.com/svn/trunk/cppguide.html]), streams should not be used except for logging. A replacement for iostream is to encapsule scanf/printf yourself.

0

I only have a programming range of 1 computer, so not much testing. Anyhow, std::cout is way more faster on my build using the exact verbose code. I am using Cpp14.

I just think certain people have a pick for C++. Yes C is great language but logically I don't see how printf can be faster than std cout. Printf has to do type conversions from void pointer on runtime. Cout does that at compile time.

  • If iostreams are in fact faster on your platform, it would be useful to know what that platform is. The reason that iostreams tend to be a lot slower than printf is that iostreams use a huge number of function calls, including a lot of virtual function calls (an iostream doesn't do *anything* by itself, it forwards everything to a `streambuf` virtual function). That's very useful if you have a need to redirect the streams, but wasteful if you aren't using it. – Ben Voigt May 22 '18 at 02:27
  • Okay I don't really know what platform you refer to, but I am using Win 10, Intel Celeron CPU G3900, 4 gigs Ram, CPP 14. You should remember CPP evolves every three years. A lot of function calls are compiled away. –  May 26 '18 at 03:58
  • Which compiler and which C++ standard library are very important details of the platform... the CPU (which you mentioned, and also contains cache information) and the RAM (which you mentioned only size but not clock rate, DDR generation, number of channels, or latency) are less important in this case but can sometimes have a big effect on performance and optimization. – Ben Voigt May 30 '18 at 03:19
0

I tried this test on my laptop, running Windows 10, WSL Ubuntu, CLion 2018, GCC. No optimization:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>

int main(int argc, char *argv[]) {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::clock_t start;
    double duration1, duration2;

    std::cout << "Starting std::cout test.\n";
    start = std::clock();

    for (int i = 0; i < 100000; i++) {
        std::cout << "Hello, World! (" << i << ")" << std::endl;
    }

    duration1 = (std::clock() - start) / (double) CLOCKS_PER_SEC;

    std::cout << "Starting std::printf test.\n";
    start = std::clock();

    for (int i = 0; i < 100000; i++) {
        std::printf("Hello, World! (%i)\n", i);
        std::fflush(stdout);
    }

    duration2 = (std::clock() - start) / (double) CLOCKS_PER_SEC;

    std::cout << "Time taken: cout " << duration1 << std::endl;
    std::cout << "Time taken Printf: " << duration2 << std::endl;

    return 0;
}

Results:

Test1: Cout: 2.25, Printf: 2.45312  (Cout run first)
Test2: Cout: 2.42188, Printf: 2.07812 (Printf Run first)
Test3: Cout: 2.26562, Printf: 2.25 (Cout run first)
Test4: Cout 2.46875, Printf: 2.57812 (Printf run first)

TL;DR: Using std::ios_base::sync_with_stdio(false) and std::cin.tie(nullptr) brings both functions to almost the same stand.

AKJ
  • 950
  • 2
  • 13
  • 18