I am reading about 3 million rows from a file and inserting them into STL maps. So, inside my while loop where I read each line from the file, I also print to console what row number it is through a simple cout statement. One of my friends recently pointed out that this makes code slower. I was wondering whether it is true and if it is why?
- 1If it's doing something extra then obviously it will be slower.Pubby– Pubby2013-01-28 23:56:30 +00:00Commented Jan 28, 2013 at 23:56
- 7Yes, it makes it much slower. Output operations are slow. Just try it outAndy Prowl– Andy Prowl2013-01-28 23:56:39 +00:00Commented Jan 28, 2013 at 23:56
- 2"One of my friends recently pointed out that this makes code slower." - at what point didn't your curiosity make you simply try it out for yourself?Mitch Wheat– Mitch Wheat2013-01-28 23:57:57 +00:00Commented Jan 28, 2013 at 23:57
- Even though I might empirically prove to myself that it makes it slow doesn't change my understanding of why.Zanam– Zanam2013-01-28 23:59:24 +00:00Commented Jan 28, 2013 at 23:59
- 3Doing stuff does take time, and printing to a console is one of the slowest things you can do.Carl Norum– Carl Norum2013-01-29 00:02:25 +00:00Commented Jan 29, 2013 at 0:02
3 Answers
As already mentioned, writing to the terminal is almost definitely going to be slower. Why?
depending on your OS,
std::coutmay use line buffering - which means each line may be sent to the terminal program separately. When you usestd::endlrather than '\n' it definitely flushes the buffer. Writing the data in smaller chunks means extra system calls and rendering efforts that slow things down significantly.some operating systems / compilers are even slower - for example, Visual C++: https://connect.microsoft.com/VisualStudio/feedback/details/642876/std-wcout-is-ten-times-slower-than-wprintf-performance-bug-in-c-library
terminals displaying output need to make calls to wipe out existing screen content, render the fonts, update the scroll bar, copy the lines into the history/buffer. Especially when they get new content in small pieces, they can't reliably guess how much longer they'd have to wait for some more and are likely to try to update the screen for the little bit they've received: that's costly, and a reason excessive flushing or unbuffered output is slow.
Some terminals offer the option of "jump scrolling" which means if they find they're say 10 pages behind they immediately render the last page and the earlier 9 pages of content never appear on the screen: that can be nice and fast. Still, "jump scrolling" is not always used or wanted, as it means output is never presented to the end users eyes: perhaps the program is meant to print a huge red error message in some case - with jump scrolling there wouldn't even be a flicker of it to catch the user's attention, but without jump scrolling you'd probably notice it.
when I worked for Bloomberg we had a constant stream of log file updates occupying several monitors - at times the displayed output would get several minutes behind; a switch from the default Solaris xterm to rxvt ensured it always kept pace
redirecting output to /dev/null is a good way to see how much your particular terminal is slowing things down
Comments
As already mentioned, writing to the terminal is almost definitely going to be slower. Why?
- Buffering:
Writing to the terminal uses line buffering* by default. This means the contents of the buffer are transmitted everytime a newline is encountered. When writing to a file, the buffer is flushed only when the buffer becomes full or when you flush the stream manually. This is the main reason for the difference as the number of I/O operations is significantly different.
*: This is true for Unix implementations, but other implementations may be unbuffered (see discussion in comments).
- Rendering:
When you write to a terminal, this involves rendering on the screen, and depending on the terminal could involve other operations that can slow your program down (not all terminals are made the same, you might find significant differences in speed by just switching to a different one).
5 Comments
cout typically defaults to fully buffered, cerr line buffered. Still, some people have the hideous habit of using std::endl unnecessarily which flushes the stream. Using \n is normally more appropriate.cout may not be fully buffered when connected to a terminal, but AFAIK it is line buffered on Unix and Windows.cin). It does say 27.4.2.3 "The object cout controls output to a stream buffer associated with the object stdout, declared in <cstdio> (27.9.2).". But - at least for UNIX stdout is line buffered when pointed at a terminal, so what you've written's good there providing cout passes data through without further buffering....If the synchronization is turned off, the C++ standard streams are allowed to buffer their I/O independently, which may be considerably faster in some cases.It's almost certainly true. Writing to the terminal is notorious for slowing things down. Run your program and redirect the output to a file and see how much faster it is. Then take out the output statement entirely and measure again. You'll see the behaviour immediately.
Here's a braindead example:
#include <stdio.h> int main(void) { int i; for (i = 0; i < 10000; i++) { printf("Hello, world!\n"); } return 0; } I built this program unoptimized and ran it, once with output to the terminal, and once with output to a file. Results for the terminal output:
real 0m0.026s user 0m0.003s sys 0m0.007s Results for redirected I/O:
real 0m0.003s user 0m0.001s sys 0m0.001s There you go, ~8x faster. And that's for a very small number of prints!
10 Comments
/dev/null? That would be an interesting comparison.