Jun 21

On Optimisations

Tag: Engine,MMORPG Tycoon,VectorStormtrevor @ 11:41 pm

There’s an old maxim amongst programmers, that premature optimisation is the root of all evil.  Or to put that in a less glib way, it’s generally a bad idea to perform optimisations before your program is completed, and it’s always a bad idea to perform optimisations if you have no way to check your performance before and after.  In practice, this means that you need to use a profiler before you start thinking about performing optimisations.

So apologies, but it’s another technical post.  For those who aren’t interested in programmer topics but are looking for pretty screenshots or discussions about game design, please feel free to skip this one.  Coders, hit the ‘Continue Reading’, below.  :)

There are several different types of profiler;  some need to be built into your program, some are external applications;  there are many different types, which are useful for different things.  Under OS X (which is where I’m currently doing my active development), there’s a free standalone profiler called “Shark”.  ”Shark” is a statistical profiler, which means that it stops your program hundreds or thousands times per second, and checks to see what your program is doing at each of those points in time.  Based upon statistical analyses of the data it obtains, it can figure out which bits of your program seem to be taking the longest to run.

There are two things which have been annoying me about MMORPG Tycoon 2 recently;  one is how long it takes for the program to build the world when it starts up (after it opens its window, it takes about five seconds on my laptop before it’s ready to render the world), and the other is how long it takes to shut the game down (quitting takes about two and a half seconds).

For fun, I ran Shark over MMORPG Tycoon today, just to see why these two things were taking so long.  In the current builds, the world terrain is being built using some simple Perlin noise.  While the noise is simple, it’s actually quite expensive to calculate so much of it.  I won’t be using Perlin noise for much longer, so I was curious to see just how much speed I was going to recover when I stopped using all that complex math.  I was also concerned about how long it must be taking to create and set up the terrain quad trees.

As it turned out, though the Perlin noise and the quad trees weren’t very expensive at all.  In fact, there were two major culprits.  The profiler pointed out a really slow piece of code in the model building process;  I had a slow ‘for’ loop copying data from one place to another.  Replacing it with a simple memcpy() fixed that one.  The other culprit was repeatedly re-generating the same pieces of data during the world building process, instead of using data I’d already calculated.  I re-architected the world building to reuse the data which it had already calculated, and that sped things up even more.  The Perlin noise is still definitely slow, but fixing these two other issues brought down the startup time from 5 seconds to about 1.5 seconds.  I’m much happier with that speed!  I had also expected that building terrain quadtrees was going to be a major expense, but it turned out to be extremely minor.

For the shutdown, it turned out that all the time being taken was occurring inside my memory management system (which is what I’d been half-expecting).  What I hadn’t expected to find was actually what was the particular operation that was using up so much time.  The problem was that the VectorStorm engine’s memory management was doing some extensive error checking on each block when it was freed;  making absolutely sure that the engine knew about the block of memory being deallocated before touching it in any way.  While that’s nice for testing purposes, it was really a bit overboard;  removing the silliest of the sanity checking brought the game’s shutdown time down from about two seconds to almost instantaneous.

Moral of the story:  Profile your code before you decide what needs to be sped up.  If I’d just jumped in and started changing the things which I’d assumed were slow, I would never have found several of the big culprits;  they were tiny little things which I’d written many, many months ago;  not the things which actually sounded complicated and slow.

4 Responses to “On Optimisations”

  1. Dan Haraj says:

    While I know that premature optimization is evil, and you shouldn’t optimize without measuring, I think it is still very important to write code in the first place conscious of performance. I think that a lot of the optimizations you can do in C++ are just idiomatic, or should be idiomatic. Things like copying memory should be done the way the hardware wants it done.

    Like copying resources from system to video memory. DX10, for example, finishes a copy at the start of the second frame after the copy command is issued. So a piece of software should be aware of that and try to access resources at the most optimal times. Otherwise, it will block needlessly. There are other things, like being cache aware. You could write an inner loop naively, measure later, and optimize later, or you could keep in mind cache effects and make sure you’re iterating through elements in a sane manner when you write it :)

    But things like your memory code, which is very well written might I add, definitely could only be caught with proper measurement and optimization.

  2. trevor says:

    All good points! (And thank you for the nice comment on my memory code!)

    My point wasn’t that you should ignore performance until after having finished your code; rather, I was suggesting that once you’ve written a block of code, it’s probably not worth going back and trying to improve its speed until (a) your program is complete enough that you’re certain that code will actually be in the final version and (b) you’ve done profiling tests and verified that the code actually is slow enough that it’s worth optimising.

    Which I think is more or less what you’re saying as well. :)

  3. Paul says:

    here’s something you may find interesting on optimization, and fuel your feelings of justification on the matter:

    http://forums.introversion.co.uk/introversion/viewtopic.php?t=2003

  4. trevor says:

    Yep, I totally agree with that forum post. The Introversion guys tend to know what they’re talking about. Except when it comes to their devotion toward Multiwinia, which has always sort of baffled me.