I’m testing a few C/C++ funcs through having them write out 100,000 lines of data (total amounting to about 3MB) to a file.
The results: Building these with Visual Studio 2005 VC++ on Win 32:
fprintf is faster than ofstream
(fprintf nearly 2x as fast as ofstream on my machine)
fwrite is marginally faster than fprintf
(fwrite about 1.1x as fast as fprintf on my machine)
// OFSTREAM IS SLOW!! #include <fstream> using namespace std; #include <stdio.h> #include <windows.h> LARGE_INTEGER ticksPerSecond; LARGE_INTEGER time1; LARGE_INTEGER time2; float floatDiffTime; const int runs = 100000; int main() { //////////////// // Get the speed of the CPU QueryPerformanceFrequency( &ticksPerSecond ); printf( "Your computer does %lld ticks per second\n", ticksPerSecond.QuadPart ); // %lld means type "long long" int, which is the // 64 bit int which is what we want here. // define some random valued variables to use // in the print statements int a = 5; double b = 9.2919e92; char c = 'x'; char * d = "blah blah blah"; // test start: open a file to write to FILE * outfile = fopen( "testfile.txt", "w" ); ///////////////////// // START timing QueryPerformanceCounter( &time1 ); // test fprintf(), run 100000 times! for(int i = 0; i < runs; i++) { fprintf(outfile, "blah %i %f %c %s\n", a, b, c, d ); fflush( outfile ); // flush to be fair } //////////////////// // STOP timing QueryPerformanceCounter( &time2 ); // get the difference between time1 and time2, // and that is how long the for loop took to run. floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; printf( "fprintf took %f seconds\n", floatDiffTime ); fclose( outfile ); // close up, so we // can proceed to start over with // ofstream test. //////////////// // testing ofstream() ofstream out( "oftestout.txt" ); //////////////////// // START timing QueryPerformanceCounter( &time1 ); // //////////////////// // test ofstream, run 100000 times! for(int i = 0; i < runs; i++) { out << "blah " << a << " " << b << " " << c << " " << d << endl; out.flush(); // flush to be fair } //////////////////// // STOP timing QueryPerformanceCounter( &time2 ); // //////////////////// // get the difference between time1 and time2, // and that is how long the for loop took to run. floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; printf( "ofstream took %f seconds\n", floatDiffTime ); out.close(); return 0; }
But what about fprintf() vs fwrite()?
Place your bets!
// what's faster, fwrite or fprintf? #include <stdio.h> #include <stdlib.h> #include <windows.h> LARGE_INTEGER ticksPerSecond; LARGE_INTEGER time1; LARGE_INTEGER time2; float floatDiffTime; const int runs = 100000; char buf[255]; // create a buffer for fwrite to use int main() { //////////////// // Get the speed of the CPU QueryPerformanceFrequency( &ticksPerSecond ); printf( "Your computer does %lld ticks per second\n", ticksPerSecond.QuadPart ); // %lld means type "long long" int, which is the // 64 bit int which is what we want here. // define some random valued variables to use // in the print statements int a = 5; double b = 9.2919e92; char c = 'x'; char * d = "blah blah blah"; // test start: open a file to write to FILE * outfile = fopen( "testfile.txt", "w" ); ///////////////////// // START timing QueryPerformanceCounter( &time1 ); // test fprintf(), run 100000 times! for(int i = 0; i < runs; i++) { //fprintf(outfile, "blah %i %f %c %s\n", a, b, c, d ); // making fprintf() print a single string generated // by sprintf() to equalize the test sprintf( buf, "blah %i %f %c %s\n", a, b, c, d ); // its only fair! fprintf( outfile, "%s", buf ); fflush(outfile); // flush after going to the toilet } //////////////////// // STOP timing QueryPerformanceCounter( &time2 ); // get the difference between time1 and time2, // and that is how long the for loop took to run. floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; printf( "fprintf took %f seconds\n", floatDiffTime ); fclose( outfile ); // close up, so we // can proceed to start over with // fwrite test. //////////////// // testing fwrite() outfile = fopen( "testfile.txt", "w" ); //////////////////// // START timing QueryPerformanceCounter( &time1 ); // //////////////////// // test fwrite(), run 100000 times! for(int i = 0; i < runs; i++) { // fwrite needs a single string to write from, // so use sprintf to copy to a buffer sprintf( buf, "blah %i %f %c %s\n", a, b, c, d ); fwrite( buf, 1, strlen( buf ), outfile ); fflush(outfile); // flush } //////////////////// // STOP timing QueryPerformanceCounter( &time2 ); // //////////////////// // get the difference between time1 and time2, // and that is how long the for loop took to run. floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; printf( "fwrite() took %f seconds\n", floatDiffTime ); fclose( outfile ); return 0; }
In my tests here, fwrite() was faster, even though using fwrite requires an extra call to strlen().
Anyway, this was just for fun. For all intents and purposes, fprintf() is pretty much the same speed as fwrite(). BUT fprintf is DEFINITELY much faster than ofstream!
Visual Studio 2005 project files for fprintf vs ofstream test hosted by esnips (thanks esnips!)
7 Comments
The same test under linux (2.6 kernel, gcc 3.5.3 tho i doubt that matters) return almost equal speeds (fprintf is still a tad faster tho). However i personally prefer fstream as it is much much easier to use, so unless you’ll be doing heavy I/O i see no reason not to use it.
What appen when compiling code for speed (-O3 with GCC) ?
Does the compiler compensate the slowliness of C++ over C ?
My experience is similar: in my test fprintf() is 4-5 times faster than ofstream (writing 500’000 lines of double’s to a file).
Forgot to say that I use C++Builder (Borland compiler)
endl implies a flush on buffered streams, so I guess you’ve let ofstream flush twice each time.
fstream was faster on linux 3.2.0-23 32-bit using GCC 4.6.3.
fprintf took 2.330000 seconds
ofstream took 1.150000 seconds
fwrite() took 2.430000 second
Another test that would be interesting is to compare fwrite() and fprintf() by sending larger data sets to the
OS file IO subsystem to explore the differences in how this is handled:
//Test fprintf
char buf[HUGE_NUMBER];
int index = 0;
//clock measurement here
memset(buf,”, HUGE_NUMBER);
for(i=0; i= HUGE_NUMBER) {
fprintf(outfile, “%s”, buf );
index = 0;
memset(buf,”, HUGE_NUMBER);
}
}
fflush(outfile)
//clock measurement here
//Test fwrite
memset(buf,”, HUGE_NUMBER);
for(i=0; i= HUGE_NUMBER) {
fwrite( buf, 1, strlen( buf ), outfile );
index = 0;
memset(buf,”, HUGE_NUMBER);
}
}
fflush(outfile)
//clock measurement here
This would shed some light on how the underlying I/O buffering is used, and whether you can help optimize it to the large data set by requesting large data writes (for example, if HUGE_NUMBER is many times the threshold at which the OS will execute pending write operations)