C++ streams (with gcc) still too slow and bugs?!

Written by Walter

Why are cpp sstream's still so slow and maybe also contain a conversion bug?

Here follows a simple example (okay did not try to optimize anything here,
just used sstream in a classroom type example and compared it to the c-style
sprintf and strtod functions).

What we notice is :
1. The cstreams implementation is almost 5 times faster than cppstreams
2. The cppstreams gives an extra double which differs from original
after conversion to string and back. The differences between value and repVal are normal/understandable but it's not logical why the cpp stringstreams have one more difference between value/repVal than when using srtod+sprintf...

Here are my files and a testrun:


wschrep@pascal:~/cpp-work/streambench.cpp> ls
cppstreams.cpp cppstreams.out cstreams.cpp cstreams.out Makefile
wschrep@pascal:~/cpp-work/streambench.cpp> cat cppstreams.cpp
#include <iostream>
#include <sstream>

using namespace std;

int main(){
double value = 1.0;
double repVal= 0;
for( int i=0;i<100000;i++){
value = (value/2)+1;

//double to string
ostringstream os;
os << value << endl;
string strVal = os.str();

//string to double
istringstream is( strVal );
is >> repVal;
if( repVal != value ){
cout << "repVal = "<<repVal<<" != value =" << value <<endl;
}
}
cout << "done!"<<endl;
return 0;
}

wschrep@pascal:~/cpp-work/streambench.cpp> cat cstreams.cpp
#include <iostream>
#include <sstream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>

int main(){
double value = 1.0;
double repVal= 0;

for( int i=0;i<100000;i++){
value = (value/2)+1;

//double to string
char cp[255];
sprintf( cp, "%f", value );
string strVal( cp );

//string to double
char * pEnd;
repVal = strtod( strVal.c_str(), &pEnd );
if( repVal != value ){
cout << "repVal = "<<repVal<<" != value =" << value <<endl;
}
}
cout << "done!"<<endl;
return 0;
}

wschrep@pascal:~/cpp-work/streambench.cpp> cat Makefile
INCLUDE = -I.
CXX = g++
CXXFLAGS = -O2 -Wall $(INCLUDE)

all: cppstreams cstreams

cppstreams: cppstreams.o
$(CXX) $(CXXFLAGS) -o cppstreams cppstreams.o

cstreams: cstreams.o
$(CXX) $(CXXFLAGS) -o cstreams cstreams.o
clean:
@rm -vf *.o *~ DEADJOE cppstreams cstreams

wschrep@pascal:~/cpp-work/streambench.cpp> make
g++ -O2 -Wall -I. -c -o cppstreams.o cppstreams.cpp
g++ -O2 -Wall -I. -o cppstreams cppstreams.o
g++ -O2 -Wall -I. -c -o cstreams.o cstreams.cpp
g++ -O2 -Wall -I. -o cstreams cstreams.o
wschrep@pascal:~/cpp-work/streambench.cpp> time ./cppstreams > cppstreams.out

real 0m1.558s
user 0m1.557s
sys 0m0.001s
wschrep@pascal:~/cpp-work/streambench.cpp> time ./cstreams > cstreams.out

real 0m0.334s
user 0m0.331s
sys 0m0.002s
wschrep@pascal:~/cpp-work/streambench.cpp> diff cstreams.out cppstreams.out
0a1
> repVal = 1.98438 != value =1.98438


So wassup here dudes? Don't have time to find a mailing list to post this so I'm just gonna put it here in my DIY blog :)

Incidently I was benching these 2 methods of conversion for my matrix class which will have to do such conversions from string to double and other types when parsing scripts and interpreting them...
For now I'm probably going to write a little wrapper class around the c-style conversion I guess... since it gives such a speed improvement ;)

Back to archive