When we develop software we always apply the best practice of not optimizing prematurely. This plays together with other best practices like writing the most readable code, or YAGNI.
‘Premature’ means different things in different situations. If you don’t have performance problems it means that there is absolutely no point in optimizing code. And if you do have performance problems it means that Thou Shalt Never Guess which code to optimize because software developers are very bad at this. The keyword here is profiling.
Since we don’t like to be “very bad” at something we always try to improve our skills in this field. The skill of guessing which code has to be optimized, or “profiling in your head” is no different in this regard.
So most of the times in profiling sessions, I have a few unspoken guesses at which parts of the code the profiler will point me to. Unfortunately, I have to say that I am very often very surprised by the outcome.
Surprises in performance fixing sessions are common but they are of different quality. One rather BIG surprise was to find out that std::string::find of the C++ standard library is significantly slower (by factor > 10) than its C library counterpart strstr (discovered with gcc-4.4.6 on CentOS 6, verified with eglibc-2.13 and gcc-4.7).
Yes, you read right and you may not believe it. That was my reaction, too, so I wrote a little test program containing only two strings and calls to std::string::find and std::strstr, respectively. The results were – and I’ve no problem repeating myself here – a BIG surprise.
The reason for that is that std::strstr uses a highly optimized string matching algorithm version whereas std::string::find works with straight-forward memory comparison.
So when doing profiling sessions, always be prepared for shaking-your-world-view kind of surprises. They can even come from your beloved and highly regarded standard library.
UPDATE: See this stackoverflow question for more information.
4 thoughts on “Performance Hogs Sometimes Live in Most Unexpected Places”
Very interesting !
I didn’t know that and like you said, it’s a big suprise… It’s weird the the find algorithm does not use string matching algorithm…
On my simple check, searching for a “needle” of 1000 characters in a 100k haystack, string::find is SOUNDLY beaten by strstr on Linux — UNTIL I assign the result of the strstr to a volatile const char * to make sure the optimizer doesn’t remove the strstr altogether, and then strstr loses to string::find by a margin of about 4:1…
I don’t know if that’s the right size range for your test case, but just make sure the optimizer isn’t being clever and removing the strstr altogether.
I even tried with different optimizer settings (-O0 .. -O3) with the same results.
Makes sense… Once I made my string and needle a bit more complex, strstr started beating string::find on most platforms I tested, too.