Best way to cache and re-access entity queries in the same frame?

Yes I keep hearing it’s getting optimized soon but I’ve been waiting quite a bit. Plus upgrading to Unity 2020 is mandatory now, thats a whole other thing. But I’m willing to get over the hurdle when it comes at least. I really wish these optimizations were transparent and on a schedule that we could rely on.

In regards to the MonoBehaviour example, that’s how I personally manage all my MonoBehaviours. It’s how it would have to work for the fixed simulation anyway in my use case. I much prefer explicit updates vs the Update monobehaviour methods (personally). So the code is using a single MonoBehaviour update hook from the “test” and it’s responsible for the code flow to call methods on other monobehaviours. Maybe I’m just particular, but I wouldn’t do it any other way for this simulation thing. Deterministic ordering would be a nightmare otherwise. Perhaps another convo :stuck_out_tongue:

But thank you for the more detailed response and shining some hope my way.

Yes in hindsight, I really wish I didn’t use ECS in its current state. Coupled with the Unity 2020 upgrades, it’s been an unfortunate ride in hair pulling. All my systems thankfully are manually updated so I don’t have to run them every frame if I don’t need to.

Thanks, I wasn’t understanding the unmanaged system stuff you were mentioning until @ just explained that it’s coming. I see now. The systems will be unmanaged types, interesting. I hope it will indeed be faster.

Several problems have us avoiding the scheduling for the time being. Designers don’t know anything about ECS so it’s just the programmers doing the ECS logic right now and we’re all new to it. The overhead of .Schedule calls means everyone has been avoiding it rather than trying to map out what could be scheduled. But we’ll get there hopefully. In the simulation loop it’s tough because most of it has to be done in order and by the end of the frame.

Typically, if the simulation is running, all these systems should be able to update. So every system should be able to have [AlwaysUpdate] I think. It could be a worthy speed up based on this test, I’m surprised I was able to measure such a big delta on the Pixel.

Just to bump this, I intend at some point to update my test project to the newest entities and try the burst systems mentioned. I really hope to not see 0.88ms on a single system anymore!

What I can’t find in the change list for 0.17 is whether job schedule overhead was improved as well. I’d like to hope so but once I find time to update we can see.

I’ve since abandoned ECS due to this issue but I’m still following along because I am interested in the tech. I would like to revisit it in the future with a new game.

Using the same benchmark code I previously shared, these are new results on my personal windows 10 machine with a Ryzen 5600x (since upgraded from what I last posted)

Reminder: 64 systems each, Jobs Leak Detection off and JobsDebugger off, 10 entities

Unity 2020.1.17f1
0.11.1-preview.4
Monobehaviour (Pretend Entities) = 0.02ms
ForEachSystem = 1.97ms (1.58ms foreach)
ForEachAlwaysUpdate = 0.28ms (0.13ms foreach)
ForEachNoBurst = 1.93ms (1.80ms foreach)

0.17.0-preview.41
Monobehaviour (Pretend Entities) = 0.02ms
ForEachSystem = 1.20ms (1.04ms foreach)
ForEachAlwaysUpdateSystem = 0.29ms (0.14ms foreach)
ForEachNoBurstSystem = 2.03ms (1.89ms foreach)

Improvements are improvements! I won’t lie and not say I hoped for more out of box but it’s a step. The AlwaysUpdateSystem is unfortunately the best way to go still.

As for SystemBase… well… it took me hours to set it up the same way I use my traditional systems. Mainly because all the of extension methods needed for manual unmanaged world creation are flagged as internal! And there’s no exposed API in SystemBase I could find besides UnmanagedUpdate which is also flagged as internal, as well as ResolveSystemState as used in ComponentSystemGroup. So you cant even manually call Update() directly on these yet.
https://forum.unity.com/threads/world-extensions-for-unmanaged-systems-are-not-public.1043650/
and docs like this are empty
https://docs.unity3d.com/Packages/com.unity.entities@0.17/api/Unity.Entities.ISystemBase.html

Because I’m insane and reluctantly decided to spend more time on this, I forked it locally and modified the Entities package and made a few tweaks to expose all the methods I needed to grab the handles to the new systems and I manually resolve the state on my side, then call into the burst code, at the same point I do the previous tests. Results:

Jobs Leak Detection off and JobsDebugger off
Also I ignore the first warmup frames for this, JIT creates ALOT of GC Alloc in these the first time it hits.
ForEachSystem(NewIBase) = 0.19ms (0.18 ms job, entire systemstateresolve 0.21ms)
ForEachNoBurstSystem(NewIBase) = 0.29ms (0.27 ms job, entire systemstateresolve 0.31ms)

This is a real win if you’re willing to go the distance to fork 0.17 and expose everything, and the headache of figuring out the entry point to call the code like the actual SystemGroup would call it (ie calls Shouldrun to check entitiy queries)

Still, however, Monobehaviour wins this by a considerable amount. And Im sure these numbers spike on device, but I do not have the Pixel 2 anymore to compare.

It’s a great direction though. I will maybe revisit Entities in the future.