-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Improve Performance of Entities::alloc_at #18054
Copy link
Copy link
Closed
Labels
A-ECSEntities, components, systems, and eventsEntities, components, systems, and eventsC-PerformanceA change motivated by improving speed, memory usage or compile timesA change motivated by improving speed, memory usage or compile timesS-Needs-DesignThis issue requires design work to think about how it would best be accomplishedThis issue requires design work to think about how it would best be accomplishedS-Ready-For-ImplementationThis issue is ready for an implementation PR. Go for it!This issue is ready for an implementation PR. Go for it!X-ContentiousThere are nontrivial implications that should be thought throughThere are nontrivial implications that should be thought through
Metadata
Metadata
Assignees
Labels
A-ECSEntities, components, systems, and eventsEntities, components, systems, and eventsC-PerformanceA change motivated by improving speed, memory usage or compile timesA change motivated by improving speed, memory usage or compile timesS-Needs-DesignThis issue requires design work to think about how it would best be accomplishedThis issue requires design work to think about how it would best be accomplishedS-Ready-For-ImplementationThis issue is ready for an implementation PR. Go for it!This issue is ready for an implementation PR. Go for it!X-ContentiousThere are nontrivial implications that should be thought throughThere are nontrivial implications that should be thought through
Entities::alloc_atandalloc_at_without_replacementcurrently have performance issues. See this conversation for the full background.When and why is it slow?
Both these functions currently have a linear search through the
pendinglist to try to find and remove the requested entity. When there are lots ofpendingentities, this is very slow.See also the source.
Practical Impact
In the conversation mentioned above, a user was spawning waves of sprite projectiles. Each wave was ~90,000 entities and was spawned and desawned over 8 seconds, repeating for each wave. This lead to measurable frame drops because, on the second wave, the render world was using
alloc_at_without_replacementwith 90,000 entities in the pending list. For massive, wave oriented games, this is a big deal.Solution
Add a field to
EntityMetathat stores the index of the entity in thependinglist if it is fee. This will remove the linear search and fix the problem.Downside:
EntityMetawill be bigger, so less of them can fit in cache. This is relevant to lots of very hot paths.Alternatives
We could try to keep the
pendinglist small by not storing tail entities. For example, if there are 16 entries inmetaand entities of index 8-15 are in the pending list, we could remove them since their pending nature could be implied by shorteningmeta. But this gives extra overhead and can be ruined by keeping just one high-index entity around.We could also try to pack the index of the entity in the
pendinglist into some other fields ofEntityMeta. Maybetable_rowor something, but that looses/invalidates other information about the entity. If anyone has a way of doing this without dropping some information, this would be an ideal solution.Finally, we could sort the pending list after
Entities::flush. This could let us change the linear search to a binary search, but keeping the sorted invariance may have additional overhead.