Why the performance of my string formatting code (via snprintf /
std::ostringstream) is so poor?
I was trying to do some performance testing of the
google::dense_hash_map and run into a following problem with a very
poor performance of the snprintf/ostringstream. Somehow the same
"%0.12f" string formatting code in C++ appears to perform ~10 times
_worse_ than in Python. Can somebody give me a pointer why and how can
I get better performance in C++?
Following code that do 10,000,000 snprintf("%0.12f") takes 7 seconds
to execute (Linux/GCC 4.3.3 with -O2):
time_t seconds = time (NULL);
char buf[20];
for(int i = 0; i < 10000000; i++)
snprintf(buf, sizeof(buf), "%0.12f", 0.123456789101);
std::cout << time(NULL) - seconds << " seconds" << std::endl;
More C++-ish approach with ostringstream is even worse - 11 seconds:
std::ostringstream str;
str << std::setprecision(12);
for(int i = 0; i < 10000000; i++)
{
str.str(std::string());
str << 0.123456789101;
str.str();
}
In Python 2.6.2 the same code takes ~1.1 seconds to execute:
start = time.time()
for i in xrange(10000000): s = "%0.12f" % 0.123456789101
print "%f seconds" % (time.time() - start)
I'm positive that in all these cases (including python) actual string
formatting is being performed. By the way, the complete test that I'm
trying to do is:
In Python:
import os, random, collections, time
d = collections.defaultdict(int)
start = time.time()
for i in xrange(10000000):
d["%0.12f" % random.random()] += 1
print "%f seconds" % (time.time() - start)
print d.iteritems().next()
And in C++ (see below, the code is too large to fit). If somebody
could improve my C++ example and outperform python, it could be nice.
So far my C++ code is slower and eats about the same amount of
memory :'-(
-- With Regards,
Dmitry Chichkov
-- With "gcc -std=c++0x -lstdc++ -O2" --
#include <google/dense_hash_map>
#include <iostream>
#include <string>
#include <random>
#include <sstream>
#include <string>
#include <iomanip>
#include <time.h>
using std::hash;
typedef std::mt19937 eng_t;
typedef std::uniform_real<double> dist_t;
int main()
{
eng_t eng;
dist_t dist(0.0, 1.0);
std::variate_generator <eng_t, dist_t > gen(eng, dist);
google::dense_hash_map<std::string, int, hash<std::string> > gm;
gm.set_empty_key("");
time_t seconds = time (NULL);
std::ostringstream str;
str << std::setprecision(12);
for(int i = 0; i < 10000000; i++)
{
str.str(std::string());
str << gen();
gm[str.str()] += 1;
}
std::cout << time(NULL) - seconds << " seconds" << std::endl;
std::cout << str.str() << " " << gm[str.str()] << std::endl;
std::cout << str.str().length() << " " << str.str().capacity() <<
std::endl;
return 0;
}