Reputation: 16113
I've been hacking at a problem on and off for several days now that lists filenames that exceed the Windows MAX_PATH
limit.
I'm using Visual Studio 2008 with all the patches I can find. The timing is done with QueryPerformanceCounter and company.
The latest issue occurs in the following code:
start = getTime();
for( vector<wstring>::iterator it = files.begin(); it != files.end(); ++it )
{
#if USE_COUT
wcout << setw( 6 ) << it->length() << L": " << *it << endl; // 1
#else
wstring x( *it );
wprintf( L"%6.6d: %s\n", it->length(), x.c_str() ); // 2
#endif
}
stop = getTime();
The above loop runs over a vector with 6755 entries with an average string length of 256 characters.
The code that prints via wcout takes roughly 52 seconds to display the vector using the loop above. The code that uses wprintf prints in about 1.2 seconds.
If I minimize the console window the printf code runs in about 500 milliseconds while the wcout code still takes about 40 seconds.
I've really tried to like iostreams over the years, but... I keep butting my head on this speed issue. In 1993/1994 when using the Borland OS/2 compiler, we had a similar issue with a runtime that took 4 to 6 hours to complete using an strstream that ran in about 200 milliseconds with sprintf.
Any suggestions to get me to change my mind about iostreams?
\n
in a printf
string functionally the same as std::endl
in the sense that both cause a newline and flush to be emitted to the output?printf
without a \n
does not print on some OS's until a buffer is filled or the stream is flushed, including Windows in the past.wprintf( "%6.6d: %s\n", length, string )
is flushed by the \n
, why isn't wprintf
as slow as wcout
?
Thanks for your feedback/opinions. I wish I had had SO 18 years ago when I started hacking at this stuff.
Upvotes: 3
Views: 1391
Reputation: 31435
It is very likely to speed you up a lot by not flushing your stream every iteration (use '\n' rather than endl), although my guess is that you will still find printf to be faster.
You might move the setw outside of your loop too, by the way.
Upvotes: 1
Reputation: 941267
Optimizing code to make it less likely that a human can keep up with the blur of scrolling lines of text doesn't make a lot of sense. Rethink this approach. Output to a text file, use HTML perhaps to make it look decent, then start a program to display the result. Easier on your user's eyes. It's going to run a lot faster as well, no auto-flushing and no time spent scrolling the console. Only the disk I/O is your bottleneck now.
Upvotes: 1
Reputation: 361292
wcout << setw( 6 ) << it->length() << L": " << *it << endl; // 1
One way to speed up is to use "\n"
instead of endl
in the loop, as endl
is more than just a newline!
Upvotes: 2
Reputation: 19940
It is very likely that the std::endl
line terminator is causing the performance bottleneck, since it flushes the stream after putting the newline. Exchange it with '\n'
and a std::wcout << std::flush
at the end of all output.
start = getTime();
for( vector<wstring>::iterator it = files.begin(); it != files.end(); ++it )
{
wcout << setw( 6 ) << it->length() << L": " << *it << '\n'; // 1
}
std::wcout << std::flush;
stop = getTime();
Upvotes: 8