The point of it is to not require branching. Like as a specific example from one of my sandboxes take a “Machine” that does work in a game, when it is given a set of items to work on then it gets a ‘MachineWorkingOn’ component, which holds the state of what it is doing and when it will complete, output, what resources it is drawing, etc… Systems that work on such things as
<ElectricalSink, MachineWorkingOn> will be processing these entities for the split second or 5 seconds or 5 minutes or whatever it works on per game tick to deduct power from the electrical network and add that to the processing time on the MachineWorkingOn component (among other things). Most entities that will potentially have
MachineWorkingOn will be idle most of the time, thus not having that component (think about 1-10 ticks to process fast recipes, another couple of ticks to remove the output item and load the new inputs, then the components are added on again).
The great majority of
ElectricalSink components will not have a
MachineWorkingOn, could be transformers, motors, etc… etc… There will be literally hundreds of thousands of entities with
ElectricalSink components. There will be large swaths that flicker on and off (and large swaths that are idle due to insufficient resources or insufficient output). This has been no processing issue for me in the past, even with quite literally a million entities.
Queries are still very valuable, and should absolutely be a focus of optimisation.
However, adding and removing components is also extremely common in ECS games, to the tune of, depending on the size of the game, hundreds to tens of thousands of additions/removals per tick (if not more in some cases).
Thus having to move all the memory of all the components that an entity holds for those operations, of which many/most of those entities will not be trivially sized, or having to use an
Option and test for the components status when most of them would very well be inactive most of the time (output backup and resource starvation is not at all uncommon) is a significant amount of work needing to be done for no reason at all. Combine that with the fact that the active and inactive ones will be very well intermixed and that blows the branch prediction of the CPU away.
This is not an uncommon action, just like queries are focused on optimization, adding/removing components do as well.
A library optimized for where you do not often add or remove components is a dataflow library, not an ECS library, and is for different purposes than an ECS.
The big thing is that legion could optimize this well by just implementing the group pattern. It would not complicate the API (it would keep it near identical other than specifying which group a component should be in, and that’s a compile-time definition).