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

Written by Walter on x/x/2004

< >

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:

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;
}


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;
}


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


Now compile and benchmark run:


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