Data locality / contiguous memory
See original GitHub issueThis is an R&D issue. I’d be happy if you guys participate if you have ideas or experience in this field. The following problem is inherent to ECS architecture afaik.
History / current state / Motivation
Over time Entitas became faster and faster as I constantly optimize and profile all the features. The biggest leap in performance was to not store components in Dictionaries anymore but use Arrays instead. Component access time improved by a factor of 60x. This approach sacrifices memory in favor of speed. With the introduction of multiple pools I provided a mechanism to improve the memory footprint of entities to address this issue. Currently entities store components in an array of a fixed size. If you have 200 components, each entity that you create has an array of capacity 200 to potentially store all components. Using multiple pools and assigning components to one or more of those pools results in entities with a smaller array. E.g. you have 2 pools, each with 100 components assigned (instead of 200), an entity only has to reserve memory for 100 components instead of 200. Awesome.
Currently this array is of type IComponent[], this means it stores pointers to the components. When you have a class PositionComponent, the pointer to this object will be stored. If you create a struct PositionComponent it will be boxed because the array is of type IComponent[] and again, the pointer is stored.
This means components are all over the place in the heap. This is actually not really a problem. Entitas is battle tested on low-end mobile devices and proofed to be very efficient even with lots and lots of entities.
But since I’m striving for the best of the best performance possible it would be nice to find a solution to improve data locality / contiguous memory / CPU cache misses.
Ideas
Components as struct
This would currently not improve anything, because of boxing. Any ideas no avoid this?
Drop the array
Don’t use an array at all… Use the code generator to generate actual fields in the entity. Generate multiple Entity types based on the pool to avoid every entity having fields for all possible components.
Your suggestions (share your ideas)
Issue Analytics
- State:
- Created 7 years ago
- Comments:29 (19 by maintainers)

Top Related StackOverflow Question
https://jacksondunstan.com/articles/3453 https://jacksondunstan.com/articles/3468 https://jacksondunstan.com/articles/3325 https://jacksondunstan.com/articles/3740
I had a discussion with @jamesmintram once about the size of the entity and why we use multiple pools. He proposed something interesting. As a pointer on an 64bit arch takes 8 bytes, what if the entity would store not an array of pointers but an array of indexes which can be 1 or 2 bytes big. Now if we say components are managed by a coordinator which has an array of components pre wormed, as @arne-schroppe and @braaad suggested, than entities can ask component coordinator/manager to replace, “destroy” or give them new components, where they get only an index. Components than can be structs or classes. As the coordinator holds only particular type of component no boxing should happen. We should have an annotation, which let user define how many entities s/he intend to have in the game. If it is lower than 255 than we could even use 1byte index inside the array. 2bytes -> 65535 entities should be enough for most of the games. The annotation could be added to every component or just to the pool.
All that sad I think the most important point was mentioned by @braaad . We need a few very good tests in order to see if what we do make sense not only on “paper” but in real world scenario. Also I liked the idea of FlagComponents being just part of the bit field/mask.