I have no preference here, just posting it as an interesting further reading.
The way I see ECSs is that they are in-memory relational databases that only support equijoins (look up component matching entity ID) and optimize for table scans. The typical choice of an index structure is a contiguous ordered array, making for very fast lookups and scans. If insertion/deletion performance becomes an issue you can add one level of indirection and only keep a list of pointers to components ordered. However, like you indicated, games also need other kinds of queries, so scene graphs and quad trees should be supported as indices on the same level as the arrays and hash tables that are traditional for ECSs.
I would love to see an in-memory database with all the features required by games. There are some very different tradeoffs to be made than in typical in-memory databases:
- The most important queries are known up-front, since the simulation/rendering loop is fairly defined.
- Transactions don't need to be durable. Just need to be able to checkpoint once in a while.
- Lots of bulk updates from the simulation.
- Query language needs to be well integrated into the application language to avoid overheads.
His basic thought on ECS is that it's "obvious". And if you have worked on an involved game a few times and tried to examine the performance bottlenecks of the architecture, it really is. There are different flavors of "how to ECS" that make tradeoffs between static compile-time composition(theoretical fastest ECS: an entire scene is fed into a compiler and it emits a custom bespoke memory layout and an API for it) and runtime dynamism(most flexible ECS: dynamic types, reflection, some code to automatically maintain indexes). But the basic principles of working directly with compositions of plain old data are ingrained throughout, and emerge naturally from trying to extend a simple game with simple data structures and an imperative code style, without resorting to OO inheritance(which was tried and discarded because properties inevitably crept upwards into the parent class leading to a memory-hungry "God Object").
It was specifically designed and developed for involved systems.
Really simple with Elixir, but the naive implementation has some potential performance issues methinks.