Game optimization series
- Game optimization: Introduction
Let's start with a trick question - which way to increment an integer by one is the fastest?
i++; // A ++i; // B i+= 1; // C i = i + 1; // D
Think about it when reading this article.
What is optimization?
Optimization is the process of modifying the code so that the resulting program uses resources in a more optimal way, usually by reducing CPU or memory usage. For the purpose of this series, we'll be talking about CPU optimization but a lot of the things are interchangeable regardless of what you want to optimize.
Code optimization's importance is mostly exceeded by how misapplied it is by people who can't know better or should know better. It easy to think that just because you should optimize late that you don't have to care about speed of your code - you have. How to write with performance in mind is a huge topic worthy many books, as such in this series I'll exclusively concentrate on types of optimizations you may encounter and, most importantly, when to optimize an how to do it.
When to optimize?
As late as reasonably possible is the best quick answer I can give you. Usually, there is no point in optimizing things before you can have a sense of scale since your work can amount to barely a percentile of increase in speed. And you could've spent the time working on things that actually make a difference.
A good starting point is when you notice something is lagging behind, you get FPS drops, loading screens take longer than comfortable, etc. Slowdowns at early stages of development suggests that something is seriously wrong with your architecture and it's wise to take a closer look.
How to locate code that needs optimization?
Use a profiler. It's the best, easiest, fastest and most reliable way to find out which parts of your game are slow. CPU sampling mode is what you should default to, as it has negligible overhead and gives you reliable relative data. If it's not possible then go with instrumentation, though the additional overhead may distort the results, mainly by inflating otherwise small functions.
In a pinch you can write your own instrumentation equivalent by wrapping your code fragment with
DateTime.Now.Ticks but chances are whatever language you use has a profiling tool.
And always, always profile a release build.
How to optimize?
It's a truism, but what you need to do is take the slow code and transform/replace it with a fast one. Change architecture, swap algorithms, change data types, introduce caching... All of those things will be covered in subsequent articles in this series.
A word about examples
In order to make the examples used in this series easier to comprehend I'll use the same hypothetical game in every single one of them.
It'll be the new best roguelike out there. It will have everything a true RL needs - ASCII graphics, colors, dragons which are represented by uppercase
D and a requirement for being fast. Not only that, it will simultaneously feature turn-based and real-time mechanics, off-grid movement and other things that you normally would not find in a roguelike but hey, we're talking about the best one out there. And it's name is PerformRL.
The question from the beginning of the article
Remember the question I stated at the beginning? What I meant when I said it's a trick question was that none of the answers is correct. The correct on is it doesn't matter.
It doesn't matter which of those is the fastest. It doesn't matter if you wrote a test suite that reliably identifies which one is the fastest and you used it exclusively in your code. It doesn't matter because the changes would improve reduce CPU usage by such a small number CERN would fail to detect it. It's as much a waste of time as using a fork to fill a bucket with water when you can just grab a hose.
Don't optimize unless you know you need it.