172
\$\begingroup\$

After looking into optimization a bit, I have discovered (literally everywhere) that it seems to be a universally recognized sin to optimize a game too early.

I really don't understand this, would it not be incredibly difficult to change some of the core structures of the game at the end, rather than developing them the first time with performance in mind?

I get that waiting until the game is finished will tell you if you even need optimizations, but shouldn't you do it anyway, after all, it could widen the variety of devices the game could run on, which would increase the number of potential players.

Could someone explain to me why it's such a bad idea to optimize too early?

\$\endgroup\$
13
  • 3
    \$\begingroup\$ It couldn't be easier to answer this: "it wastes time". You might as well ask "why try to save money when shopping?" \$\endgroup\$
    – Fattie
    Commented May 24, 2017 at 10:51
  • 29
    \$\begingroup\$ Conversely, note that many engineers quite simply say that the sentence "don't optimize too soon" is simply wrong. The sentence should be, simply, "don't optimize until you know what to optimize". So, quite simply, if there are three systems A, B and C, it is utterly pointless optimizing A if, it turns out, A is not in any way whatsoever a bottleneck, and C is in fact the bottleneck. In that example, obviously, optimizing A would have been an utter waste of time. So - quite simply - don't optimize until you know which of A, B C to optimize: that's all it means, it's that simple. \$\endgroup\$
    – Fattie
    Commented May 24, 2017 at 10:56
  • 1
    \$\begingroup\$ @Fattie If you read the question and not just the title, it's obvious that Matthew is explicitly talking about the problem of "Isn't it more expensive to optimise a finished, complex system than optimising on every step?" "Don't optimise until you know what to optimise" is pointless advice - it tells you nothing about how you know when you know what to optimise, which is what's really being asked here. It's funny that you consider the question "tautological", and your response has no information whatsoever :) \$\endgroup\$
    – Luaan
    Commented May 24, 2017 at 16:58
  • 4
    \$\begingroup\$ Optimizing the time class of your application during development is very different than trying to shave a few instructions out of a loop which is usually constant time. Focus on O(n) vs O(n log n) instead of, "writing a for loop this way saves one CPU instruction". \$\endgroup\$
    – user101510
    Commented May 25, 2017 at 21:17
  • 1
    \$\begingroup\$ @phyrfox Actually, reducing the load time seems more impressive to me. Three seconds load time is noticeable. I'm not sure if 55fps to 60fps is noticeable. \$\endgroup\$
    – user20574
    Commented May 28, 2017 at 4:33

10 Answers 10

245
\$\begingroup\$

Preamble:

A few objections have been raised in the comments, and I think they largely stem from a misunderstanding of what we mean when we say "premature optimization" - so I wanted to add a little clarification on that.

"Don't optimize prematurely" does not mean "write code you know is bad, because Knuth says you're not allowed to clean it up until the end"

It means "don't sacrifice time & legibility for optimization until you know what parts of your program actually need help being faster." Since a typical program spends most of its time in a few bottlenecks, investing in optimizing "everything" might not get you the same speed boost as focusing that same investment on just the bottlenecked code.

This means, when in doubt, we should:

  • Prefer code that's simple to write, clear to understand, and easy to modify for starters

  • Check whether further optimization is needed (usually by profiling the running program, though one comment below notes doing mathematical analysis - the only risk there is you also need to check that your math is right)

A premature optimization is not:

  • Architectural decisions to structure your code in a way that will scale to your needs - choosing appropriate modules / responsibilities / interfaces / communication systems in a considered way.

  • Simple efficiencies that don't take extra time or make your code harder to read. Things like using strong typing can be both efficient and make your intent more clear. Caching a reference instead of searching for it repeatedly is another example (as long as your case doesn't demand complex cache-invalidation logic - maybe hold off on writing that until you've profiled the simple way first).

  • Using the right algorithm for the job. A* is more optimal and more complex than exhaustively searching a pathfinding graph. It's also an industry standard. Repeating the theme, sticking to tried-and-true methods like this can actually make your code easier to understand than if you do something simple but counter to known best practices. If you have experience running into bottlenecks implementing game feature X one way on a previous project, you don't need to hit the same bottleneck again on this project to know it's real - you can and should re-use solutions that have worked for past games.

All those types of optimizations are well-justified and would generally not be labelled "premature" (unless you're going down a rabbit hole implementing cutting-edge pathfinding for your 8x8 chessboard map...)

So now with that cleared up, on to why we might find this policy useful in games specifically:


In gamedev especially, iteration speed is the most precious thing. We'll often implement and re-implement far more ideas than will ultimately ship with the finished game, trying to "find the fun."

If you can prototype a mechanic in a straightforward & maybe a bit naive way and be playtesting it the next day, you're in a much better position than if you spent a week making the most optimal version of it first. Especially if it turns out to suck and you end up throwing out that feature. Doing it the simple way so you can test early can save a ton of wasted work optimizing code you don't keep.

Non-optimized code is also generally easier to modify and try different variants on than code that's finely-tuned to do one precise thing optimally, which tends to be brittle and harder to modify without breaking it, introducing bugs, or slowing it way down. So keeping the code simple and easy to change is often worth a little runtime inefficiency throughout most of development (we're usually developing on machines above the target spec, so we can absorb the overhead and focus on getting the target experience first) until we've locked down what we need from the feature and can optimize the parts we now know are slow.

Yes, refactoring parts of the project late in development to optimize the slow spots can be hard. But so is refactoring repeatedly throughout development because the optimizations you made last month aren't compatible with the direction the game has evolved since then, or were fixing something that turned out not to be the real bottleneck once you got more of the features & content in.

Games are weird and experimental — it's hard to predict how a game project and its tech needs will evolve and where the performance will be tightest. In practice, we often end up worrying about the wrong things — search through the performance questions on here and you'll see a common theme emerge of devs getting distracted by stuff on paper that likely is not a problem at all.

To take a dramatic example: if your game is GPU-bound (not uncommon) then all that time spent hyper-optimizing and threading the CPU work might yield no tangible benefit at all. All those dev hours could have been spent implementing & polishing gameplay features instead, for a better player experience.

Overall, most of the time you spend working on a game will not be spent on the code that ends up being the bottleneck. Especially when you're working on an existing engine, the super expensive inner loop stuff in the rendering and physics systems is largely out of your hands. At that point, your job in the gameplay scripts is to basically stay out of the engine's way - as long as you don't throw a wrench in there then you'll probably come out pretty OK for a first build.

So, apart from a bit of code hygiene and budgeting (eg. don't repeatedly search for/construct stuff if you can easily reuse it, keep your pathfinding/physics queries or GPU readbacks modest, etc), making a habit of not over-optimizing before we know where the real problems are turns out to be good for productivity - saving us from wasting time optimizing the wrong things, and keeping our code simpler and easier to tweak overall.

\$\endgroup\$
17
  • 39
    \$\begingroup\$ There's some further discussion on StackOverflow here, emphasizing the importance of readability and clarity in code, and the danger of making code harder to understand (and easier to introduce bugs into) by prematurely optimising it. \$\endgroup\$
    – DMGregory
    Commented May 21, 2017 at 23:54
  • 8
    \$\begingroup\$ Great answer, I'd like to add, in response to "would it not be incredibly difficult to change some of the core structures of the game at the end, rather than developing them the first time with performance in mind?" directly, that of course you try to design for efficiency in the first place. When presented with two choices, you pick the more efficient one. Failing that, you write the game as modularly as possible with well defined interfaces. You can then change the mechanisms within each module without restructuring the entire codebase. \$\endgroup\$
    – Baldrickk
    Commented May 22, 2017 at 8:00
  • 1
    \$\begingroup\$ @Baldrickk I'd say that's worth sharing as an additional answer. (I'd upvote it!) My answer skips over the importance of architecture and planning to avoid creating big problems in the first place. As for Gizmo's reference to "program development in general," that's where this concept of premature optimization comes from. As outlined above, the wrong optimization can become technical debt just as easily as a missing optimization. But we should emphasise that we're never doing things in a deliberately slow way, just preferring simplicity & legibility until we can profile & find the real issues \$\endgroup\$
    – DMGregory
    Commented May 22, 2017 at 9:17
  • 1
    \$\begingroup\$ While I am probably most inexperienced here out of You folks, I must say I find this "premature optimization root of all evil" a little weird. Two years ago or so I was trying to do something in Unity3D. I wrote a few LINQ queries, each using the previous one. I looked at my code and started having strong doubts. I thought the computation complexity was horrible. I took a sheet of paper and calculated that processing these queries on an expected size of data would take hours. So I added a little caching here and there. And the queries were running fine. \$\endgroup\$
    – gaazkam
    Commented May 23, 2017 at 17:34
  • 3
    \$\begingroup\$ So you did due diligence and verified that the problem was real before changing your code from what was initially clearest and most intuitive to you. That means your optimization wasn't premature. ;) "Avoid overoptimizing prematurely" doesn't mean "write unnecessarily expensive code" — just to favour simplicity, legibility, ease of modification until a definite performance problem has been identified. The comments aren't intended for discussion, so we can move to chat if you'd like to talk about this further. \$\endgroup\$
    – DMGregory
    Commented May 23, 2017 at 17:39
44
\$\begingroup\$

Note: this answer began as a comment on DMGregory's answer, and so doesn't duplicate the very good points he makes.

"Would it not be incredibly difficult to change some of the core structures of the game at the end, rather than developing them the first time with performance in mind?"

This, to me, is the crux of the question.

When creating your original design, you should try to design for efficiency - at the top level. This is less optimisation, and is more about structure.

Example:
You need to create a system to cross a river. The obvious designs are a bridge or a ferry, so which do you choose?
The answer of course depends on the size of the crossing and the volume of traffic. This isn't an optimisation, this is instead starting out with a design suited for your problem.

When presented with design choices, you pick the one best suited to what you want to do.

So, let's say that our volume of traffic is fairly low, so we decide to build two terminals and buy in a ferry to handle the traffic. A nice simple implementation.
Unfortunately, once we have it up and running, we find that it is seeing more traffic than expected. We need to optimise the ferry! (Because it works, and building a bridge now isn't a good plan)

Options:

  • Buy a second ferry (parallel processing)
  • Add another car deck to ferry (compression of traffic)
  • Upgrade the ferry's engine to make it faster (re-written processing algorithms)

This is where you should attempt to make your original design as modular as possible.
All of the above are possible optimisations, and you could even do all three.
But how do you make these changes without large structural changes?

If you have a modular design with clearly defined interfaces, then it should be simple to implement these changes.
If your code is not tightly coupled, then changes to modules don't affect the surrounding structure.

Let's take a look at adding an extra ferry.
A 'bad' program might be built around the idea of a single ferry, and have the dock states and ferry state and position all bundled together and sharing state. This will be hard to modify to allow for an extra ferry being added to the system.
A better design would be to have the docks and ferry as separate entities. There isn't any tight coupling between them, but they have an interface, where a ferry can arrive, unload passengers, take on new ones, and leave. The dock and ferry share only this interface, and this makes it easy to make changes to the system, in this case by adding a second ferry. The dock doesn't care about what ferries there actually are, all it is concerned with is that something (anything) is using its interface.

Summary:

  • Try to design for efficiency in the first place.
  • When presented with two choices, you pick the more efficient one.
  • Write your code as modularly as possible with well-defined interfaces.

You can then change the mechanisms within each module without restructuring the entire codebase when you need to optimise.

\$\endgroup\$
6
  • 17
    \$\begingroup\$ At the beginning you can also implement your ferry as IRiverCrossing, and when it becomes clear that volume of traffic is too great for the ferry set up, implement the bridge as IRiverCrossing and drop it in. The trick of course is reducing the external API of the Ferry and the Bridge to common functionality so they can be represented by the same interface. \$\endgroup\$
    – Mr.Mindor
    Commented May 22, 2017 at 14:51
  • 3
    \$\begingroup\$ You might even have automated tests written for these modular interfaces, so you could refactor quickly without much worry about breaking anything outside of the module that you're touching. \$\endgroup\$ Commented May 22, 2017 at 21:07
  • 2
    \$\begingroup\$ Very nice example of why OOP is so important these days. \$\endgroup\$
    – user101384
    Commented May 23, 2017 at 15:59
  • 1
    \$\begingroup\$ You hit the right reason. Donald Knuth's mantra is only true when speed is not one of the core requirements, and a focus on optimization would compromise the main design. Alas, in games speed often is at the core, and hence must be factored into the design early on. The OP's concern (and your answer) is entirely justified. \$\endgroup\$ Commented May 24, 2017 at 7:26
  • 1
    \$\begingroup\$ @JaimeGallego it doesn't even need to be OOP. You can achieve this in almost any language. For example, if you are using one of many APIs to perform a function, then if you create a common interface instead of making the API calls directly, switching APIs is as simple as replacing the wrapper that implements the interface. It's all abstraction and indirection, whether you use OOP or not. This was literally one of the first things hammered into us when I did my CS degree. OO languages are designed to make it easier though. \$\endgroup\$
    – Baldrickk
    Commented May 24, 2017 at 9:47
25
\$\begingroup\$

"Do not optimise early" doesn't mean "pick the worst possible way to do things". You still need to consider performance implications (unless you're just prototyping). The point is not to cripple other, more important things at that point in development - like flexibility, reliability etc. Pick simple, safe optimisations - choose the things you limit, and the things you keep free; keep track of the costs. Should you use strong-typing? Most games did and work fine; how much would it cost you to remove that if you found interesting uses of the flexibility for gamemplay?

It's much harder to modify optimised code, especially "smart" code. It's always a choice that makes some things better, and others worse (for example, you might be trading CPU time for memory usage). When making that choice, you need to be aware of all the implications - they might be disastrous, but they can also be helpful.

For example, Commander Keen, Wolfenstein and Doom were each built on top of an optimized rendering engine. Each had their "trick" that enabled the game to exist in the first place (each also had further optimizations developed over time, but that's not important here). That's fine. It's okay to heavily optimize the very core of the game, the think that makes the game possible; especially if you're exploring new territory where this particular optimized feature allows you to consider game designs that weren't much explored. The limitations the optimization introduces may give you interesting gameplay as well (e.g. unit count limits in RTS games may have started as a way to improve performance, but they have a gameplay effect as well).

But do note that in each of these examples, the game couldn't exist without the optimization. They didn't start with a "fully optimized" engine - they started with the bare necessity, and worked their way up. They were developing new technologies, and using them to make fun games. And the engine tricks were limited to as small part of the codebase as possible - the heavier optimizations were only introduced when the gameplay was mostly done, or where it allowed an interesting new feature to emerge.

Now consider a game you might want to make. Is there really some technological miracle that makes or breaks that game? Maybe you're envisioning an open-world game on an infinite world. Is that really the central piece of the game? Would the game simply not work without it? Maybe you're thinking about a game where the terrain is deformable without limit, with realistic geology and such; can you make it work with a smaller scope? Would it work in 2D instead of 3D? Get something fun as soon as possible - even if optimizations might require you to rework a huge chunk of your existing code, it may be worth it; and you might even realize that making things bigger doesn't really make the game better.

As an example of a recent game with lots of optimisations, I'd point to Factorio. One critical part of the game are the belts - there are many thousands of them, and they carry many individual bits of materials all around your factory. Did the game started with a heavily-optimised belt engine? No! In fact, the original belt design was almost impossible to optimise - it kind of did a physical simulation of the items on the belt, which created some interesting things you could do (this is the way you get "emergent" gameplay - gameplay that surprises the designer), but meant you had to simulate every single item on the belt. With thousands of belts, you get tens of thousands of physically-simulated items - even just removing that and letting the belts do the work allows you to cut the associated CPU time by 95-99%, even without considering things like memory locality. But it's only useful to do that when you actually reach those limits.

Pretty much everything that had anything to do with belts had to be remade to allow the belts to be optimised. And the belts needed to be optimised, because you needed a lot of belts for a large factory, and large factories are one attraction of the game. After all, if you can't have large factories, why have an infinite world? Funny you should ask - early versions didn't :) The game was reworked and reshaped all over many times to get where they are now - including a 100% ground-up remake when they realized Java isn't the way to go for a game like this and switched to C++. And it worked great for Factorio (though it was still a good thing it wasn't optimised from the get-go - especially since this was a hobby project, which might have simply failed otherwise for lack of interest).

But the thing is, there are lots of things you can do with a limited-scope factory - and many games have shown just that. Limits can be even more empowering for fun than freedoms; would Spacechem be more fun if the "maps" were infinite? If you started with heavily optimised "belts", you would pretty much be forced to go that way; and you couldn't explore other design directions (like seeing what interesting things you can do with physics-simulated conveyor belts). You're limiting your potential design-space. It may not seem like that because you don't see a lot of unfinished games, but the hard part is getting the fun right - for every fun game you see, there's probably hundreds that just couldn't get there and were scrapped (or worse, released as horrible messes). If optimisation helps you do that - go ahead. If it doesn't... it's likely premature. If you think some gameplay mechanic works great, but needs optimisations to truly shine - go ahead. If you don't have interesting mechanics, don't optimise them. Find the fun first - you will find most optimisations don't help with that, and are often detriminal.

Finally, you have a great, fun game. Does it make sense to optimise now? Ha! It's still not as clear as you might think. Is there something fun you can do instead? Don't forget your time is still limited. Everything takes an effort, and you want to focus that effort on where it matters most. Yes, even if you're making a "free game", or an "open source" game. Watch how the game is played; notice where the performance becomes a bottleneck. Does optimising those places make for more fun (like building ever bigger, ever more tangled factories)? Does it allow you to attract more players (e.g. with weaker computers, or on different platforms)? You always need to prioritise - look for the effort to yield ratio. You'll likely find plenty of low-hanging fruit just from playing your game and watching others play the game. But note the important part - to get there, you need a game. Focus on that.

As a cherry on top, consider that optimisation never ends. It's not a task with a little check mark that you finish and move on to other tasks. There's always "one more optimisation" you can do, and a big part of any development is understanding the priorities. You don't do optimisation for optimisation's sake - you do it to achieve a particular goal (e.g. "200 units on the screen at once on a 333 MHz Pentium" is a great goal). Don't lose track of the terminal goal just because you focus too much on the intermediate goals that might not even be pre-requisites for the terminal goal anymore.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ I believe the factorio developers are now optimizing belts again so that they only need to simulate items periodically, and at all other times it just interpolates their position when you're looking at them. But they're only just doing that now when the entire game's been effectively based around belts (and robots) for a long time and not until people started noticing and complaining about the performance. \$\endgroup\$
    – user20574
    Commented May 24, 2017 at 0:43
  • 3
    \$\begingroup\$ @immibis Exactly. Making it perform better before people actually reached the limits would be a waste of resources, that are better spent elsewhere. Even with the latest optimisations, you most likely encounter the problem for only the megafactories well beyond the scope of normal gameplay (launching the rocket). But it enabled the new Marathon gameplay settings, which require far heavier logistics. And again, they identified the bottlenecks by getting statistics from people actually playing the game - about half of the bottlenecks were a big surprise to them. \$\endgroup\$
    – Luaan
    Commented May 24, 2017 at 9:39
  • \$\begingroup\$ @Fattie So you understand the question, but not the answer? Are you just trying to say that a simpler answer is possible (e.g. "Economics")? I don't see how your comment is supposed to be constructive. \$\endgroup\$
    – Luaan
    Commented May 24, 2017 at 14:58
  • 2
    \$\begingroup\$ @Fattie If you think the answer is "Optimize only once you know what is the bottleneck", post it as an answer. You've already spent a lot more words than would be required for a good answer, so go ahead. What kind of optimisation doesn't make things better and worse? I've certainly never seen one. The fundamental thing I keep reiterating is that it's always a trade-off - time that could be better spent elsewhere, complexity that limits your flexibility... The examples point out that "early" is not an absolute term; some optimisations are necessary from day one, while others are detriminal. \$\endgroup\$
    – Luaan
    Commented May 24, 2017 at 16:46
  • 1
    \$\begingroup\$ @Fattie "Optimize only once you know what is the bottleneck" is the answer to "When should I optimize?" and is not an answer to "Why is it so bad to optimize too early?". \$\endgroup\$
    – user20574
    Commented May 24, 2017 at 22:44
9
\$\begingroup\$

A lot of the answers seem to be focusing a lot on the performance aspect of "optimization" while I myself like to look at optimization and the whole ordeal of optimizing too early at a more abstract level.

Humor me as I attempt to elaborate on my perspective with the help of polyominoes.

Suppose we have some fixed boundaries set by the framework or engine we're working with.

enter image description here

We then proceed to create our first layer/module of the game like so.

enter image description here

Moving onwards we build our second layer/module.

enter image description here

At this point, we might notice that there is some space available between the two modules and we might be tempted to optimize it to make full use of the boundaries allotted to us.

enter image description here

Perfect, now the application is fully utilizing the resources available to us, the application is better, good right?

We proceed to build the third layer/module of our application and suddenly we come to a realization (perhaps even one we could not have foreseen during initial planning) that the 3rd layer/module is not working for us.

We search for an alternative, we find one, and in the end, this also requires us to change the 2nd module of our application since it's incompatible with our newly selected 3rd module. (Thankfully it's somewhat compatible with our 1st module so we don't have to re-write everything from scratch.)

So we put it all together...

enter image description here

Hmm, can you see what happened?

By optimizing too early we now have actually made things worse efficiency-wise since what we optimized against is not what we ended up with down the line.

And if we would have wanted to add some additional modules or extra tidbits afterward, we might no longer have the capacity to do them at this point.

enter image description here

And adjusting the lowest level of our system is no longer that feasible since it has been buried under all of the other layers.

If, however, we would have opted to wait with our urge to optimize it immediately we would have ended up with something like this:

enter image description here

And now if we perform the optimization at this point we get something satisfying to look at.

enter image description here

Hopefully at least some of you had as much fun reading this as I had fun making this :) and if you now feel like you have a better grasp on the subject - all the better.

\$\endgroup\$
3
  • 4
    \$\begingroup\$ I am removing the advertisement. We don't care how you made the images; the only important part is the assumption that you have the right to post them. \$\endgroup\$
    – Gnemlock
    Commented May 25, 2017 at 13:08
  • 2
    \$\begingroup\$ @Gnemlock fair enough, while my intention was not aimed towards advertisement I can also see how it could be easily misinterpreted as such, and I will agree that it does not add anything to the answer so it has no place in it. \$\endgroup\$ Commented May 25, 2017 at 13:43
  • 3
    \$\begingroup\$ I think this visual metaphor is extremely effective. Great approach to answering the question! :) \$\endgroup\$
    – DMGregory
    Commented May 26, 2017 at 16:44
8
\$\begingroup\$

Money.

It comes down to that. Money. Since time is money*, the more time you spend on activities that are not guaranteed to generate more money (i.e. you can't consider these activities as investments), the more money you risk wasting, and the less money you'll make with the game.

Here are some more potential side effects of optimizing too early, and reasons why you should avoid it:

  • Your colleagues hate you because you play in your sandbox with your toys while they work hard to get features in.
  • The delays displease the higher management, and make the team miss delivery dates, which causes the game to be released in the spring instead of before the holiday season, which in turn causes the game to not sell enough. And because of this, the head office decides to shut-down the studio, effectively making you jobless. And no job means no money. (And since no one likes you because you spent too much time doing early optimization, no one wants to write a positive review on your work for you on LinkedIn, which will keep you out of money for a longer time.)

* Other answers have highlighted well enough the 'time' part


As a side note, generally, experience helps determining what is and what is not premature optimization and what has value for the business and what has not.

For instance, if you've worked on game A, and realized by the end of the project that the feature XYZ was particularly heavy on your game loop, and you eventually start to work on game B which has the exact same feature, deciding to rewrite the feature and optimizing it from the start is not really premature optimization, as you know it will be a bottleneck if nothing is done.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ @JBentley that is a valid point. However, there is a consequential answer to the "why" as a direct implication of the gathered experience. So, 1) optimizing early can lead to wasted time on parts of the code that do not impact the average runtime (given the experience, you should know which code constructs are candidates for optimization best practices) 2) optimizing early can make the code harder to maintain due to the design restrictions imposed over some system. You thus may gain too little in exchange for longer development cycles/cumbersome code to maintain. \$\endgroup\$
    – teodron
    Commented May 22, 2017 at 9:21
  • 3
    \$\begingroup\$ @JBentley Consider this as an addendum to DMGregory's answer. \$\endgroup\$
    – Vaillancourt
    Commented May 22, 2017 at 10:10
  • 1
    \$\begingroup\$ This would seem to be the only worthwhile answer here. The question is a tautology. You might as well ask "So why, actually, do you want a game to make more rather than less money on the app stores?" How can you answer that? \$\endgroup\$
    – Fattie
    Commented May 24, 2017 at 11:08
  • \$\begingroup\$ @Fattie It's good to have this kind of perspective in an answer. But saying it's the only worthwhile answer is narrowing the scope of the question unreasonably. You're assuming for example, that the only games made are within for-profit organizations (clearly not true). You're also assuming that it is obvious to the OP that optimizing early leads to more time being spent (and hence more money if we're talking about a business). Actually the OP's question shows that he is not sure about this. \$\endgroup\$
    – JBentley
    Commented May 24, 2017 at 12:02
6
\$\begingroup\$

Optimization is, by definition, the process of increasing the efficiency of a solution up to the point where it looses its efficacy. This process implies then a reduction of the solution's space.

At an early stage of software development there can still be "hidden requirements": if you reduces too much the space of your solution you might end up in a situation in which you are unable to satisfy a "hidden requirement" when it pops-up at a later stage of development, compelling you then to modify the architecture adding in this way instability and a possible bunch of undesidered behaviours.

The idea is then to get the entire solution working and only then, when all the requirements are fixed and implemented, tighten the code. You will see then, that a lot of optimizations you would have lightheartedly implemented at once while coding, are now no longer feasable due to the interaction with late requirements.

The real space of the solution is always bigger than the one we expect at the beginning because we cannot have a perfect knowledge of a very complex system.

Make it work first. Then tighten the ropes.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ I think "efficacy" isn't the word you're going for — it means "the power to produce an effect", so in a sense, optimisation is all about increasing efficacy. Are you going for some specific version of efficacy? (Could you link to it?) Do you instead mean something like flexibility? \$\endgroup\$ Commented May 22, 2017 at 13:44
  • 2
    \$\begingroup\$ @doppelgreener It means you make the solution more efficient up until it stops producing the effects you want... \$\endgroup\$
    – user20574
    Commented May 24, 2017 at 0:44
  • 1
    \$\begingroup\$ "Make it work first. Then tighten the ropes." - That has to be worth as much as the rest of the answer combined. And not to say the other stuff wasn't good. \$\endgroup\$
    – ebyrob
    Commented May 25, 2017 at 14:03
  • 1
    \$\begingroup\$ @ebyrob: there's another saying: "Make it work, make it right, make it fast" wiki.c2.com/?MakeItWorkMakeItRightMakeItFast \$\endgroup\$
    – ninjalj
    Commented May 29, 2017 at 10:32
  • \$\begingroup\$ @ninjalj That's a good one too. Of course, my boss always tells me: "Don't rush, make it right." So I don't know if what you are saying is as universal as the principal the original poster is requesting more detail about. \$\endgroup\$
    – ebyrob
    Commented May 29, 2017 at 14:21
2
\$\begingroup\$

In short, very often optimizing early becomes wasted effort if you want to change things later, and then it turns out you've optimized away the easily changeable code structures into something much lower level, and you now need to change it back to a high level approach, and optimize the result once again.

This is a common mistake for newbie developers who like to focus on getting pleasure from "having done useful work", like optimization, not thinking about if it's the right time to do it. As you gain experience programming big projects like games, you'll learn when it's warranted to optimize the existing codebase, and when it is too soon. Don't be afraid to make this mistake, you'll only benefit by learning from it.

In general, only optimize if you really can't work with the development build right this moment. Like if you're creating and deleting millions of objects 60 times per second.

So, I'd say it's good, in terms of learning experience, to optimize early a few times :p

\$\endgroup\$
0
2
\$\begingroup\$

Optimization focuses on making the computer work best on the code while development requires making the programmer work best on the code.

Optimization does not bring out insights. It makes the computer work less and the programmer more.

Of course, there are different categories, like with designing a car. Nothing wrong with optimizing an engine before you build your first chassis, but optimizing the chassis before you don't know the shape of the engine may end up a waste of time. Modularity and specs can get a number of places viable for optimization work even before the product as a whole gets assembled.

\$\endgroup\$
2
  • \$\begingroup\$ This would be improved by leading with something other than defining optimization, and by talking about the practical situation in game development rather than going for analogies about cars. \$\endgroup\$ Commented May 22, 2017 at 13:04
  • \$\begingroup\$ A perfect answer to a tautological question. \$\endgroup\$
    – Fattie
    Commented May 24, 2017 at 11:10
2
\$\begingroup\$

I strongly disagree with all of those statements that code shouldn't be optimized at early stages. It depends on what stage you are. If this is MVP - prototype and you are just trying to look at the game which takes from 1 to 2 weeks, that you ready to rewrite everything you already wrote. Yeah, optimization doesn't matter. But if you already are working on a game that you know will be release, it should have optimized code all along. The tales that people say about new features and things that could be added is missconception. It's poorly designed code architecture rather than optimized code. You don't need to rewrite anything to add new elements if you have nice code design.

For example, if you have a A* pathfinding algorithm, wouldn't it be better to write it the most optimal way you can? Rather than later changing half of the code you have because you had to make some changes in the algorithm because now it needs another method calls and callbacks? And if you already have an optimized code from start it will save you a lot of time. Because you can draw yourself relations between objects and how they interact, instead of blindly making tons of new scripts and making up all connections right away - this leads to unclear sphagetti code.

The last thing I want to add is that later, even if you don't want to make the game anymore, you have your optimized A* algorithm that you can use for your next games. Reusability. For example, many games have inventory, pathfinding, procedural generation, interactions between npc, fighting system, AI, Interface interaction, input management. Now you should ask yourself - "How many times have I rewritten those elements from scratch?" They are 70-80% of the game. Do you really need to rewrite them all the time? And what if they are unoptimized?

\$\endgroup\$
8
  • 6
    \$\begingroup\$ If A* code should start optimised, how optimised is "optimised"? Do you handcode things in assembly before doing benchmarks? I think generally non-trivial work on micro-optimisations should be left till benchmarks have been done. The optimising compiler might do a better job than you at micro-optimisations, and is much cheaper. \$\endgroup\$
    – gmatht
    Commented May 22, 2017 at 14:11
  • \$\begingroup\$ @gmatht Well A* can be different as I said it can have poor design and not work really well. But it can be multithreaded, based on Fibonacci heap, have some predictions, split into chunks. If we are talking about pathfinding, we can add Flow Field to be mixed with A*. Also way smoothing, multi height. Maybe A* is not the best example, but as I said, optimizations have nothing to do with actually changing the code, developer is changing the code because it was poorly designed, for example he didn't follow SOLID as 1 reason.If you have written this A* well, you don't need to write it anymore. \$\endgroup\$ Commented May 22, 2017 at 14:21
  • \$\begingroup\$ @gmatht micro optimizations are not actually the problem. I think OP means more of a the best and most efficient way of computing AI behavior or shader or anything else. \$\endgroup\$ Commented May 22, 2017 at 14:25
  • \$\begingroup\$ If you know how to write this things efficiently I don't see the problem doing so. It will take the same amount of time or even less. It depends more on a developers experience. As a programmer, if I know better solution I would not write a crappy one. If I know how to write Fibonacci heap, I won't use List and sorting to get the min or max values. Of course it will take some more time and effort to write it, instead of using List.Sort(); , but what if I already have a reusable one? \$\endgroup\$ Commented May 22, 2017 at 14:30
  • 2
    \$\begingroup\$ @CandidMoon I disagree with "It will take the same amount of time or even less." to write efficient code. Maybe it would take the same time to write code that is not obviously inefficient, but when your notion of "efficienct" means considering cache contention, adding multithreading, using CPU specific intrinsics available on only some CPUs, switching algorithms for large N due to O(N log N) vs O(N) - that kind of thing is hard and error prone and takes a lot more time than the simple implementation. You only do it when you know it is going to materially effect the final result. \$\endgroup\$ Commented May 23, 2017 at 4:52
0
\$\begingroup\$

Short and simple answer:

  1. A feature you optimize now might be a feature you throw out or replace later.
  2. If you spend too much time optimizing, you might never finish your game.
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .