1

Summary

I have this C++ code:

#include <iostream>
#include <chrono>

int main() {
    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();

    for (int counter = 0; counter < 80000;) {
        std::printf("%d\n", counter++);
    }

    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

    std::cout << std::endl << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) / 1000000.0 << std::endl;

    std::cin.get();
    return 0;
}

When running the code after compiling with g++ Source.cpp -O3, the run time is usually around 25 seconds on my machine. However, if I use g++ Source2.cpp -std=c++14 -O3 for compiling, the run time I'm getting is more than 90 seconds.

More details

I am compiling with g++ version 8.2.0 which defines __cplusplus to be 201402L. Therefore, by default, it should be compiling under the C++14 standard.

It therefore seems strange that the code would run much slower when I add the -std=c++14 flag. I also noticed that the code runs just as slow if I use -std=c++11, so it seems that just using -std= is the problem.

NB 1: I use printf() instead of cout within the loop because I am aware that the former is faster.

NB 2: My question is totally different than Code running slower with g++ -std=c++0x, even though the title might sound similar.

Update

Based on suggestions in the comments, I tried to run the code with writing to a file instead of printing to the terminal. In that case, there was no significant difference in the run times.

I also ran the code in different terminals on Windows: cmd, PowerShell, cmder. I found out that, while the exact run times are different on each terminal, the code without the -std= flag still generally runs at least twice as fast.

(When running the program on the terminals, I made sure to start a new terminal before every run, in order to ensure that the terminal history does not impact the run time.)

So, the specific question is:

Why does adding the flag make the code run slower when the code prints to a terminal?

Update 2

After running more tests, I realized that the difference is negligible when using a terminal which prints out the code in a short amount of time (a few seconds or less than a second).

It seems that the difference in run times that I was getting is peculiar to the environment of my machine and may not be replicable.

Nevertheless, the insights provided by Michael in his answer and comments are valuable and might help explain problems of a similar nature faced by others.

hb20007
  • 515
  • 1
  • 9
  • 23
  • Do you output to the terminal (which one?) or redirect to a file? – Michael Veksler Mar 01 '19 at 11:32
  • I'm outputting to the terminal. I'm using git bash on Windows – hb20007 Mar 01 '19 at 11:39
  • 1
    So most of the time is spent in the terminal. I doubt that the program itself takes much of the total time. Also, bash sounds like a shell not a terminal. The terminal is cmd, cygwin terminal, or something like that. Try measuring after you redirect to a file – Michael Veksler Mar 01 '19 at 11:43
  • I will try that. But what difference does the exact terminal I'm using make? – hb20007 Mar 01 '19 at 11:49
  • 1
    The terminal draws the pixels that represent the text. This takes much more resources than simply sending ascii chars to a process (which is what printf does, in a way). It heavily depends on the way the terminal does it (does it draw all the pixels immediately, or does it do it once in a while? How does it handle scrolling history? And so on) – Michael Veksler Mar 01 '19 at 11:53
  • 1
    If you want to benchmark with the terminal, start a new terminal (emply history) every time – Michael Veksler Mar 01 '19 at 12:00
  • @MichaelVeksler I made an edit to the question based on your feedback. – hb20007 Mar 01 '19 at 12:51
  • 1
    If you are concerned about output performance, you do have the synchronization overhead involved too. https://stackoverflow.com/questions/31524568/cout-speed-when-synchronization-is-off – Eljay Mar 01 '19 at 13:36

1 Answers1

1

The differences are solely due to the terminal. Both alternatives are writing to the terminal, which has to maintain scroll history, and draw the pixels of the written characters. The terminal works much harder than the short benchmark that only spits out ASCII characters.

In fact, your terminal (and/or OS) are extremely slow. I have run the same program (compiled with gcc-8.2.0) on a MAC terminal and it ran 0.175374 seconds, once and 0.186559 another time. Without gathering significant amount of statistical data, I could not see any difference with and without -std=c++14.

It seems an issue with an extremely slow terminal (more than 100 times slower than the MAC terminal), not with the code itself. Most likely your terminal becomes slower when it gathers history, so the second time it runs it gets slower (regardless of the compilation flags).

Edit after seeing the updated question:

It is possible that the default is -std=gnu++14 which performs some nonstandard optimization that makes the terminal run faster. When you pass -std=c++14 the gnu extension is turned off.

For a reference, look at compiling with std c11.... According to it, -std=c++14 means that _GNU_SOURCE is no longer defined, and a different implementation of printf could be used.

Community
  • 1
  • 1
Michael Veksler
  • 8,217
  • 1
  • 20
  • 33
  • In another terminal, the code without the flag runs in approximately **8 seconds** while with the flag it takes about **18 seconds**. I see that your machine is much faster than mine. Would you notice a difference with and without the flag if you loop to, say, `8000000` instead of `80000` on your machine? – hb20007 Mar 01 '19 at 12:55
  • The windows console is really slow (though it is getting better in recent windows 10 builds) – Alan Birtles Mar 01 '19 at 12:56
  • 1
    Try to add `std::flush(stdout)` right after the `printf`, and compare the runs. I suspect that with `-std=gnu++14` some of the flushes implied by `printf` are avoided, and the explicit flush will make the difference go away – Michael Veksler Mar 01 '19 at 12:58
  • I have just added some links that show that a different printf could be used with both flags. – Michael Veksler Mar 01 '19 at 13:30