Donald Knuth, the father of analysis of algorithms in computer science once said:
Premature optimization is the root of all evil.
Very wise words, but a little counter intuitive at first glance. You may say, but, isn't it better to plan optimization once you start a project so that you don't have to, like, do double the work optimizing later? And the answer is not that simple, it's a yes, and a no.
You see, when you start a project that has a lot of stuff that you really don't know what they'll be in the end, it's hard to actually gauge, code-wise, how impactful each piece of the code will be in the run time of the game. To meassure how fast an algorithm is, we use the notation O(log(n)), O(n), O(n log(n)), O(n^2), O(n^n), etc (it can be any other mathematical function, not just a power, but i'll leave it like that in here :P) and we call it its order. O(n) is good, O(n^n) is really really bad.
Premature optimization is the root of all evil.
Very wise words, but a little counter intuitive at first glance. You may say, but, isn't it better to plan optimization once you start a project so that you don't have to, like, do double the work optimizing later? And the answer is not that simple, it's a yes, and a no.
You see, when you start a project that has a lot of stuff that you really don't know what they'll be in the end, it's hard to actually gauge, code-wise, how impactful each piece of the code will be in the run time of the game. To meassure how fast an algorithm is, we use the notation O(log(n)), O(n), O(n log(n)), O(n^2), O(n^n), etc (it can be any other mathematical function, not just a power, but i'll leave it like that in here :P) and we call it its order. O(n) is good, O(n^n) is really really bad.
A small example of how, higher order algorithms quickly become more and more slow. Logarithmic is O(log(n)), linear is O(n), log linear O(n log(n)), quadratic O(n^2) and so on.
So, the thing is, unless you make an analysis of each and every algorithm in your code, you are not gonna be quite sure about how fast, or slow is each part of the game. This just gets worse if you use an engine not written by yourself, because you have no real idea about the order of each function. Now, I'm not saying using an engine like Unity or Unreal is bad, is just something that adds up to the issue at hand. And even if you wrote your own engine, if you start adding coders to the team, different approaches to a same problem can create parts of the code with different orders than expected.
Now, why is it so important to know the order of an algorithm? because if, for example, you have codes of order O(n), a very low low and fast order, there is literally no need to optimize it. Hell, you are most certainly wasting time (money) doing so. So, how do we know what to optimize? Knowing the order of Every. Single. Function. And. Method. In. Your. Game. Are you thinking that is not plaussible? that you are going to loose a ton, a huuuge ton of time to do so? and that this equates to money that our game costs? Well, that's exactly why premature optimization is so "Evil."
In the long run it's literally more cost-effective to optimize later than in the planning stage. Using tools like Unity's profiler to find which parts of your game are eating up the processing time of the game, then re-writing pieces of code and patching will be way better than trying to ultra-optimize everything from the get-go. On the other hand, experience will be your best friend, one day of course when you (we) have it :P, because you'll know beforehand that doing something in some way will eat up a lot of CPU or GPU. On the other hand, that doesn't mean you can't learn from the experience of others and not do things that experts are well aware that you shouldn't do. Reading best practices for Unity/Unreal is always a plus.
Now, why is it so important to know the order of an algorithm? because if, for example, you have codes of order O(n), a very low low and fast order, there is literally no need to optimize it. Hell, you are most certainly wasting time (money) doing so. So, how do we know what to optimize? Knowing the order of Every. Single. Function. And. Method. In. Your. Game. Are you thinking that is not plaussible? that you are going to loose a ton, a huuuge ton of time to do so? and that this equates to money that our game costs? Well, that's exactly why premature optimization is so "Evil."
In the long run it's literally more cost-effective to optimize later than in the planning stage. Using tools like Unity's profiler to find which parts of your game are eating up the processing time of the game, then re-writing pieces of code and patching will be way better than trying to ultra-optimize everything from the get-go. On the other hand, experience will be your best friend, one day of course when you (we) have it :P, because you'll know beforehand that doing something in some way will eat up a lot of CPU or GPU. On the other hand, that doesn't mean you can't learn from the experience of others and not do things that experts are well aware that you shouldn't do. Reading best practices for Unity/Unreal is always a plus.
If you forget this, Knuth will keep staring at your soul as long as you keep programming...
After all that, what did we actually do this past week? Well, we are optimizing REalM, searching all those pieces of code that hurt the game. The game runs actually pretty well, 60 fps on PS4, 30 fps on low-end laptops, but from time to time, there are some spikes, which we don't want to hurt the experience. Right now we had one special culprit for this, and wanted to share it with you all, specially with Unity users.
As you can see in the image below, it happens, according to the Profiler in GUI.Repaint. This is called by Unity if in any of your classes you use the OnGUI() method. In our case, we had the OnGUI() to monitor certain statistics of specific objects, controlled by a flag. If the flag was on false, the OnGUI() simply returned at the begining. Nevertheless, even if it does nothing, OnGUI() causes a huge overload, by commenting the method on the class, since at this point in development it is no longer used, the spikes are gone.
In other words, remember to remove unused code :P.
As you can see in the image below, it happens, according to the Profiler in GUI.Repaint. This is called by Unity if in any of your classes you use the OnGUI() method. In our case, we had the OnGUI() to monitor certain statistics of specific objects, controlled by a flag. If the flag was on false, the OnGUI() simply returned at the begining. Nevertheless, even if it does nothing, OnGUI() causes a huge overload, by commenting the method on the class, since at this point in development it is no longer used, the spikes are gone.
In other words, remember to remove unused code :P.
This is just but one of the things we did last week to optimize REalM, and we are still working on it, so when you play it, you won't have any issues with it.
- Lex
Images retrieved on June 10 from:
http://everythingcomputerscience.com/images/Algorithm_Analysis731x524.jpg
http://www.azquotes.com/picture-quotes/quote-premature-optimization-is-the-root-of-all-evil-donald-knuth-72-10-20.jpg