Because of all the impatience, I did something super quick and it still doesn’t cover my use case at the worst possible scenario. This is a super simplified workload and I still see that ForEach is slow. Like I said, caching the chunks ends up being just as fast or faster on my devices. The only exception to this is if I flag [AlwaysUpdate] on the system, this speeds it up considerably but I need to investigate if I can use that in my actual code.
Info/Conditions:
-
com.unity.entities@0.11.1-preview.4
-
10 entities (all match the use case, this is too optimal/naive for real performance numbers, it would actually be worse with more entities in a real use scenario)
-
10 frames of updates
-
64 ticks of Update per frame
-
I only have 6 ECS systems, all doing largely the same thing and poking at the same memory/entities. (Also too optimal/naive, it would be nice if I could create a bunch of systems of the same type doing dummy work but annoyingly ECS worlds are type-keyed I think which means its 1:1, would have to create dummy classes.)
-
Burst compiling = on
Job safety checks = off
-
Notice the code of the “jobs” all have early out conditions and out of box none of the entities actually end up doing anything (it sees value == 0.0f return/continue in the loop)
Method:
Attach profiler, record, press button to begin test, wait for cube to disappear, stop profiling. Open profile analyzer, pull data, highlight the test (it will be one big block of frame time, something like 10-20 frames to highlight), use name filter “test.” with the period at the end.
Unity 2019.4.7f1 In-Editor Windows
-
UpdatePretendEntities (no ECS, just MonoBeh) = 0.02ms (this is the ideal performance)
-
ForEachSystem.OnUpdate = 0.23ms
-
AlwaysUpdateForEachSystem.OnUpdate = 0.17ms
-
ForEachSystemNoBurst.OnUpdate = 0.30ms
-
ChunksSystem.OnUpdate = 0.07ms + 0.11ms (for PreLoop to cache) = 0.18ms
-
ChunksJobSystem.OnUpdate = 0.13ms + 0.11ms (for PreLoop to cache) = 0.24ms
-
ChunkJobSystemNoBurst.OnUpdate = 0.30ms + 0.11ms (for PreLoop to cache) = 0.41ms
Android Pixel 2
-
UpdatePretendEntities (no ECS, just MonoBeh) = 0.16ms (this is the ideal performance)
-
ForEachSystem.OnUpdate = 0.88ms
-
AlwaysUpdateForEachSystem.OnUpdate = 0.74ms
-
ForEachSystemNoBurst.OnUpdate = 1.03ms
-
ChunksSystem.OnUpdate = 0.37ms + 0.47ms (for PreLoop to cache) + 0.01 (for PostLoop to dispose) = 0.85ms
-
ChunksJobSystem.OnUpdate = 0.70ms + 0.47ms (for PreLoop to cache) + 0.01 (for PostLoop to dispose) = 1.02ms
-
ChunkJobSystemNoBurst.OnUpdate = 1.03ms + 0.47ms (for PreLoop to cache) + 0.01 (for PostLoop to dispose) = 1.51ms
The quickest take away is that ECS here kills performances whether you’re using ForEach or Chunks, Monobehaviours win. Of course this is just with 10 entities, rather than a million, but like I said that’s how my game operates right now. There’s usually only 1 entity these systems look at. My game does not have or will have many entities, it’s not a battle royal or anything.
For 1 system to take 0.88ms is crazy to me. Yes, it’s unusual to call update on the system 64 times. But even at 1/4 of that, it shouldn’t be breaching 0.20ms especially when the systems are not actually doing work (just conditional check). I have 70+ systems now that have to do this every frame because it’s a simulation, that’s 61.6ms at minimum (assuming 64hz) 
Non ECS would be 11.2ms for comparison
Disclaimer: besides the test favoring ForEach for several noted reasons, it is worth mentioning I could have mistakes here. I rushed this since I didn’t appreciate the rudeness I perceived. Lots of ways to make the test “closer” to my use case such as adding lots more systems, mix/match burst use, add more entity archetype variation for the chunks, don’t use the entities sequentially, introduce mixed branching of logic.
Profile files:
https://www.dropbox.com/s/qz6d8piw512d2fq/profiles.zip?dl=0
Project/Code here:
https://www.dropbox.com/s/3ii8llny18pcxwr/test.zip?dl=0
How outdated by the way? Less than a month? In the unity slack channel for DOTS it was recent, beginning of October I think. @Joachim_Ante_1