My last article was fun. The reaction is also a quite good read to learn if you have fallen into coding pitfalls:
The purpose of stress testing is to push the boundaries really hard and learn something out of it. About the technology you work with and the differences even when you work with the same language. Mission accomplished. I do hope, people learned something from it and are able to write better code with the new gained knowledge.
Just to reiterate some pitfalls when having to deal with a lot of data:
– Do not allocate anything inside loops. The GC will punish you! Allocate outside or use references.
– Use structs unless you reference it. Structs are created on the stack and classes on the heap. The stack is much faster to access for allocations and won’t be hit by the GC.
– Think what a line really does and reduce it’s complexity. If you don’t need a method call don’t use it.
UPDATE: Structs are mostly allocated on the stack but there are limitations. Read this for more details: https://msdn.microsoft.com/en-us/library/ms229017%28v=vs.110%29.aspx
Micro optimization is key here as cpu ticks quickly add up over a lot of iterations.
Time to get some perspective. How well is Factorio doing with that amount? I went back to my original test map in Factorio where I wanted to test 1 million items on 1 million belts. Turns out I could automate this creation with LUA scripting.
Their entity update takes 138-142ms.
Mine resides at around 100ms. I’ve less code paths so that’s expected, but I’ve the minimum implemented. Not just moving, but distance checking.
I had hopes that Factorio would maintain 60fps even with that amount but the test put everything a little more in perspective.
Turned out I’ve reached the goal, what was achievable in Factorio, already in Part2.
The final question: Can Factoria be done in Unity/C#? In this form, yes!
What’s not tested here is the creation and destruction of a lot of these items. For that the solution would be to maintain a reference to an EntityPool so you don’t run into constant GC spikes.
So the real question is: Is it more pain to get the engine running or handle the GC?
Personally I’d say handling the GC is easier. There are always tricks that can be used. With proper architecture these tricks are also not that hard to implement.
Creating an engine that runs on almost every hardware is a real pain though. The time lost there is probably much higher than just the GC hand holding.