Performance Tuning

In my previous article on Performance Requirements I argued that performance issues are requirements, and that this is not well understood in the software development community in general. In this article I’m going look at the performance tuning of existing code, argue that this is also poorly understood, and discuss the right way to go about it.

My friend Alan Griffiths related an experience of his from a few years ago. He was working on a desktop product written in C++. In this case the performance requirements of the software had been managed sensibly, in that performance criteria were understood. Alan was tasked with improving the performance of specific functionality by a factor of two.

How to go about this? Well, the functionality he was tasked with optimising used did quite a lot of searching and sorting of data. This had led to an implicit assumption (among some members of the development group) that this is where the improvements would be needed. However, the C++ development environment in use had a profiler, so Alan set about obtaining concrete information on where the problem really was – and the result was something of a surprise! Execution seemed to be spending a lot of time in string::operator== ! A quick look in the library source code quickly gave a clue: the operator== implementation simply called the C strcmp function. Alan decided that he had, at this point, obtained enough information to try something simple: he wrote a replacement operator== that first checked if the strings were of equal length, and simply returned false if they were not. This was enough to solve the problem! In fact, it delivered a factor of four improvement – twice as much as was deemed necessary – at no extra charge!

I have, many times throughout my career, seen programmers dive in and start speeding up code based on guesswork and unfounded assumptions – indeed, in my less experienced days I dare say I was guilty of this myself (just don’t tell anyone). This is a waste of time. Alan could easily have spent lots of time trying to optimise searching and sorting code, when this time would have been wasted. Unless you actually measure the performance of various parts of the code, you don’t know what is causing the code to under-perform. As illustrated above, this is true even if there are “obvious” candidates!

The moral of this story is a recurring theme: avoid guessing! Instead, gather concrete evidence of where the problem lies before making changes to the code.

4 Comments

  1. John January 7, 2009 at 8:27 pm

    Pedantic perhaps but you’re really looking to identify a bottleneck / which bit of code is used most (and is therefore worth optimising) rather than a “problem”. After all there’s no point optimising code that doesn’t actually work correctly.

  2. MarkR January 7, 2009 at 8:45 pm

    I think to be honest it’s semantics rather than pedantic (sorry). I would argue that if software is not meeting its performance criteria then there is a problem to be solved. However I agree with you re there being no point optimising code that isn’t working (in the functional sense), and I think this is a point I have so far made by implication, but failed to make explicit.

    Thanks for this John, as I think you’ve just handed me an idea for another article 🙂

  3. John January 8, 2009 at 11:22 am

    I’ll stick the bill in the post 😉

  4. Alan January 15, 2009 at 3:03 pm

    I think you’ve misremembered the story. The scenarios I was optimising were running much more that 2 times too slow (i.e. 10+ times slower than the existing product). This was following the replacement of a dummy persistence layer (used during development) with a persistance layer that moved inactive objects out to a database.

    The “obvious” place to look was the queries and indexes in the database or faulty logic that decided when to save or recover objects.

    As you relate, however, the problem proved to be something else entirely. Which is the main point of the story.

Leave a Comment

Your email address will not be published. Required fields are marked *