Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is std::cout so time consuming?

Tags:

c++

c++11

I have made a program to compute the permutations of an 8 character string "sharjeel".

#include <iostream>
#include <time.h>

char string[] = "sharjeel";
int len = 8;
int count = 0;

void swap(char& a, char& b){
    char t = a;
    a = b;
    b = t;
}
void permute(int pos) {
    if(pos==len-1){
        std::cout << ++count << "\t" << string << std::endl;
        return;
    }
    else {
        for (int i = pos; i < len;i++)
        {
            swap(string[i], string[pos]);
            permute(pos + 1);
            swap(string[i], string[pos]);
        }
    }
}

int main(){
    clock_t start = clock();
    permute(0);
    std::cout << "Permutations: " << count << std::endl;
    std::cout << "Time taken: " << (double)(clock() - start) / (double)CLOCKS_PER_SEC << std::endl;
    return 1;
}

If I print each permutation along it takes about 9.8 seconds for the execution to complete.

40314   lshaerej
40315   lshareej
40316   lshareje
40317   lshareej
40318   lshareje
40319   lsharjee
40320   lsharjee
Permutations: 40320
Time taken: 9.815

Now if I replace the line:

std::cout << ++count << "\t" << string << std::endl;

with this:

++count;

and then recompile, the output is:

Permutations: 40320
Time taken: 0.001

Running again:

Permutations: 40320
Time taken: 0.002

Compiled using g++ with -O3

Why is std::cout so relatively time consuming? Is there a way to print that is faster?

EDIT: Made a C# version of the program

/*
 * Permutations
 * in c#
 * much faster than the c++ version 
 */

using System;
using System.Diagnostics;

namespace Permutation_C
{
    class MainClass
    {
        private static uint len;
        private static char[] input;
        private static int count = 0;

        public static void Main (string[] args)
        {
            Console.Write ("Enter a string to permute: ");
            input = Console.ReadLine ().ToCharArray();
            len = Convert.ToUInt32(input.Length);
            Stopwatch clock = Stopwatch.StartNew();
            permute (0u);
            Console.WriteLine("Time Taken: {0} seconds", clock.ElapsedMilliseconds/1000.0);
        }

        static void permute(uint pos)
        {

            if (pos == len - 1u) {
                Console.WriteLine ("{0}.\t{1}",++count, new string(input));
                return;
            } else {
                for (uint i = pos; i < len; i++) {
                    swap (Convert.ToInt32(i),Convert.ToInt32(pos));
                    permute (pos + 1);
                    swap (Convert.ToInt32(i),Convert.ToInt32(pos));
                }
            }

        }
        static void swap(int a, int b) {
            char t = input[a];
            input[a] = input[b];
            input[b] = t;
        }
    }
}

Output:

40313.  lshaerje
40314.  lshaerej
40315.  lshareej
40316.  lshareje
40317.  lshareej
40318.  lshareje
40319.  lsharjee
40320.  lsharjee
Time Taken: 4.628 seconds
Press any key to continue . . .

From here, Console.WriteLine() seems almost twice as fast when compared with the results from std::cout. What seems to be slowing std::cout down?

like image 710
Saad Avatar asked Mar 27 '17 16:03

Saad


People also ask

Is std :: cout faster than printf?

@rashedcs printf is definitely faster than cout because of internal syncing / flushing in iostream i/o which normally slows down their performance. However using iostream with sync_with_stdio(false) makes i/o operations comparable to scanf/printf.

Is STD cout slower than printf?

To answer your question, printf is faster.

Does cout slow program?

As already mentioned, writing to the terminal is almost definitely going to be slower. Why? depending on your OS, std::cout may use line buffering - which means each line may be sent to the terminal program separately. When you use std::endl rather than '\n' it definitely flushes the buffer.

Why is STD cout used instead of cout?

So, in that case, cout is defined in the std namespace. Thus, std::cout states that is cout defined in the std namespace otherwise to use the definition of cout which is defined in std namespace. So, that std::cout is used to the definition of cout from std namespace.


1 Answers

std::cout ultimately results in the operating system being invoked.

If you want something to compute fast, you have to make sure that no external entities are involved in the computation, especially entities that have been written with versatility more than performance in mind, like the operating system.

Want it to run faster? You have a few options:

  1. Replace << std::endl; with << '\n'. This will refrain from flushing the internal buffer of the C++ runtime to the operating system on every single line. It should result in a huge performance improvement.

  2. Use std::ios::sync_with_stdio(false); as user Galik Mar suggests in a comment.

  3. Collect as much as possible of your outgoing text in a buffer, and output the entire buffer at once with a single call.

  4. Write your output to a file instead of the console, and then keep that file displayed by a separate application such as Notepad++ which can keep track of changes and keep scrolling to the bottom.

As for why it is so "time consuming", (in other words, slow,) that's because the primary purpose of std::cout (and ultimately the operating system's standard output stream) is versatility, not performance. Think about it: std::cout is a C++ library function which will invoke the operating system; the operating system will determine that the file being written to is not really a file, but the console, so it will send the data to the console subsystem; the console subsystem will receive the data and it will start invoking the graphics subsystem to render the text in the console window; the graphics subsystem will be drawing font glyphs on a raster display, and while rendering the data, there will be scrolling of the console window, which involves copying large amounts of video RAM. That's an awful lot of work, even if the graphics card takes care of some of it in hardware.

As for the C# version, I am not sure exactly what is going on, but what is probably happening is something quite different: In C# you are not invoking Console.Out.Flush(), so your output is cached and you are not suffering the overhead incurred by C++'s std::cout << std::endl which causes each line to be flushed to the operating system. However, when the buffer does become full, C# must flush it to the operating system, and then it is hit not only by the overhead represented by the operating system, but also by the formidable managed-to-native and native-to-managed transition that is inherent in the way it's virtual machine works.

like image 130
Mike Nakis Avatar answered Nov 08 '22 11:11

Mike Nakis