Making games run faster

Or: why micro-optimising games code often helps.

I was part of a conversation on Twitter that started with a question about the relative performance of calling .GetComponent<T>() vs having a public field assigned in the inspector. I linked back to my earlier post that includes a profiling script for Unity prefabs.

In a followup to those tweets, I was asked "should I care about optimising this code if it's 0.001% of my CPU budget?" My response was "generally no," but that conversation leads me to note this more subtle point about the performance of games code.

If you're from a typical "business" programming background, writing data processing and big websites and such, you learn specific things about optimisation. Don't do it prematurely: there's no point optimising what isn't slow. Don't micro-optimise: saving a millisecond on one line of code isn't worth it when there are minutes to be saved elsewhere. The first point is still absolutely true in games but, for the second point, what constitutes "micro-optimisation" is a very different beast.

The reason for this is that most code will run in the main game loop, which runs every frame. Much code will also be run multiple times within your scene. This makes trivial wins potentially huge in terms of performance.

As an example, let's say we have a particular game agent (an NPC) and that agent has a piece of code (an AI logic routine). Assume there are 20 agents active, and our game currently runs at a paltry 20fps. This piece of logic is already running 400 times per second. That is a huge factor that makes any gain an order of magnitude better than it seems.

Imagine we can shave half a millisecond off the execution time of that code. It doesn't seem like much... except we've saved that 20 times per frame, and our frame is currently taking 50ms to complete. We've just chopped 10ms - twenty percent - off the frame time. That takes the FPS from 20 to 25, with what could be a one-line change.

The beauty of this is that the faster a game already runs, the more these tiny optimisations help, because they represent a larger percentage of the frame's CPU time. If we're running at 30fps to start with (as opposed to 20), shaving off that same half millisecond would take us up to just under 43fps.

The basic approach to optimising doesn't change: profile first, and the attack whatever the worst offender is. The difference with games code is that, often, the worst offender is a tiny piece of code that just happens to be running hundreds of times a second.

That one-line micro-fix can make a massive difference.