Benchmarking default world initialization and group update cost

When using the default world we have to pay :

  1. Scanning for all ComponentSystem available in all assemblies.
  2. Put them into 3 top-level groups and sort those groups recursively. This could be filtered out with ICustomBootstrap.

I am interested in knowing how it scales when I have a lot of systems defined in the project, and when I have filtered some of them out using ICustomBootstrap to cut out some systems. (Still the full reflection cost and iteration will remain)

(details : https://gametorrahod.com/world-system-groups-update-order-and-the-player-loop/)

All test run 100 times and averaged. Defined system is generated by something like seq 1 1000 | sed -e 's/^/public class System/' -e 's/$/ : TestSystem { }/' | pbcopy before running on a real Android device each time. The benchmark is over DefaultWorldInitialization.Initialize call on a project with default world disabled.

I think most game will ended up with 4~7 seconds startup time to get all the systems ready. (currently, preview.30) Should not be that serious considering you would do this only on start up. (But for Unity “app” if that is possible to build in the future, maybe I desire more instant start time especially that 4 seconds on low number of systems… and this 4s is a big blocker if you want to unit test the entire default world.) On the row with 10 remaining systems you could estimate the assembly reflection cost without grouping/sorting cost.

*All generated systems has no UpdateBefore/After, this may make the sorting cheaper than the real use.

Next up is after initialized, how long it take to update on all systems, assuming that all of them do not qualify for update, and then assuming that all of them qualified for update (found matching Entity for its GetEntityQuery) but that update ended up doing nothing. The benchmark is by stopwatching on the simulationGroup.Update() where all test systems live in.


Most game may have 50-200 systems. As long as you have properly design the update condition I think you can have as much as 1000 systems with no worries. Even the empty update / early out case is not that expensive. (3.6ms is expensive but you should not have 1000 empty updating systems in the first place)

6 Likes

Thanks for the tests! I’m a bit surprised by the numbers for DefaultWorldInitialization. I have similar benchmark for my own World Initialization code that shouldn’t deviate too much from DefaultWorldInitialization in terms of cost. But my numbers are an order of magnitude less (~50x less). Though I only tested on desktop.

I wonder if it’ll make any difference on your side if you put all scripts in an asmdef and untick Auto Referenced.

But anyway, I take comfort in that it’s fairly easy to roll your own Initialization code. Whether it’s to customize UpdateLoops/SystemGroups, handle Dependency Injection, or just improve load time.