C++ performance myths debunked

Neil Hodgson nhodgson at bigpond.net.au
Fri Aug 2 21:16:13 EDT 2002


Gerson Kurz:

> Download the libraries from over at www.boost.org. Compile a sample
> program (with VC6), get 31 warnings like this (I'm not making this up,
> and yes, it is *one* single warning):

   VS .NET compiles without these warnings although it does warn about
unused local variables.

> 100000 loops of that take 2609 ms. Move "string s" out of the loop,
> because it does some allocating, go down to 2300 ms.

   On my 600 MHz Athlon, this takes 770 ms with /O2 /GL optimization turned
on. Template libraries really need the optimizer as this was about 4000 ms
without optimization. The optimization may have removed some of the code
needed if any real work was being done.

> Now try the same thing with strtok. It sure doesn't look so pretty:

   It is also not quite the same output, with the default tokenizer not
including the ',' on the second token. To see the same output as strtok,
although this is unexpectedly slower:

 typedef boost::tokenizer<boost::char_separator<char> > toktok;
 boost::char_separator<char> sep(" ");
 toktok tok(s, sep);
 for (toktok::iterator beg=tok.begin(); beg!=tok.end(); ++beg) {

> 100000 loops of that takes .... TADA: 200 ms.

   135 ms for me.

> Now, lets try that in Python.
> ...
> Took 484 ms.

   1250 ms with Python 2.2. 1170 ms with -O. Nowhere near as good as you
see.

My version of the C++ code:

// cl /W4 /EHsc /I .. toktest.cxx /O2 /GL
#include <iostream>
#include <string>
#include "tokenizer.hpp"
extern "C" int _stdcall GetTickCount();
using namespace std;
using namespace boost;

int main() {
 string s = "This is,  a test";
 int start = GetTickCount();
 for (int ii=0; ii<100000; ii++) {
  tokenizer<> tok(s);
  for (tokenizer<>::iterator beg=tok.begin();
   beg!=tok.end(); ++beg) {
   const char* shit = beg->c_str();
  }
 }
 int end = GetTickCount();
 cout << "tokenizer took " << (end - start) << endl;

 start = GetTickCount();
 for (int ii=0; ii<100000; ii++) {
  char s[100];
  // create a copy of input string, because
  // strtok modifes its argument inplace
  strcpy(s, "This is,  a test");
  char* token = strtok( s, " " );
  while( token != NULL ) {
   const char* shit = token;
   token = strtok( NULL, " " );
  }
 }
 end = GetTickCount();
 cout << "strtok took " << (end - start) << endl;
}

   Neil







More information about the Python-list mailing list