I have an application that have to iterate over every character (to check some special cases) and write it to a stream using ostream put method.
When writing the ostream* points to a file stream, it executes magnificently faster than when ostream* points to cout which is redirected to a file.
In this (https://stackoverflow.com/a/1697906/12074577) answer I saw that probable using the fstream will be faster, due to one more layer of buffering compared to cout. I thought that when I know that the output is going to cout, I can go through a string buffer, and when the buffer is full, append it to cout. This way I obtain another layer of buffering and performance will improve.
So I have a test here of writing 32 million rows, each row is a string of ten characters. I write them using cout, fstream, and stringbuffer that is later appended to cout.
void print_to_ostream(ostream *out, string& ones)
{
for (int i = 0; i < 32000000; ++i){
const char* ones_char = ones.c_str();
for (int j = 0; j < ones.size(); ++j ){
out->put(ones_char[j]);
}
}
}
int main(void){
string ones ="1111111111";
ostream *out = &cout;
size_t cout_time = 0;
size_t file_time = 0;
size_t cout_buffered_time = 0;
// print cout using ostream
mono_tick_timer time;
print_to_ostream(out, ones);
cout_time += time.tick();
// write to file using ostream
ofstream file("/tmp/test_file");
out = &file;
time.tick();
print_to_ostream(out, ones);
file_time += time.tick();
// ***optional solution***
// print to cout but passing through a string buffer
stringstream buffer;
out = &buffer;
time.tick();
print_to_ostream(out, ones);
cout_buffered_time += time.tick();
cout << buffer.str();
size_t buf_to_cout = time.tick();
std::cerr << "cout time: " << (double)cout_time / 1e6 << endl;
std::cerr << "file time: " << (double)file_time / 1e6 << endl;
std::cerr << "cout buffered time: " << (double)cout_buffered_time / 1e6 << endl;
std::cerr << "buf_to_cout: " << (double)buf_to_cout / 1e6 << endl;
return 0;
}
The results of running ./a.out > /tmp/test_times
are as follow (milliseconds):
cout time: 4773.62
file time: 2391.52
cout buffered time: 2380.83
buf_to_cout: 131.615
My bottom line question is: is using stringstream as a buffer before appending everything to cout a good solution? Considering the fact that sometimes cout is redirected with large output to a file, and sometimes it's just being printed to the console?
Are they any negative side effects I didn't think about with this solution? Or there is a better one I didn't think about?
The global streams (e.g. std::cout
) are sync_with_stdio
by default, whereas std::ofstream
is not:
By default, all eight standard C++ streams are synchronized with their respective C streams.
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.
Try turning it off with std::cout.sync_with_stdio(false);
.