3 ms·
> Well, it is? If you say so we can agree on that, yes. :) > What do you mean by looping itself? I mean that that ECS is not merely looping over an array lik
by ratww 5y ago
> Well, it is?
If you say so we can agree on that, yes. :)
> What do you mean by looping itself?
I mean that that ECS is not merely looping over an array like GP claimed. In production ECS, Systems normally act on more than one kind of Component, so "iterating over the array" of components is not feasible. Iterating over entities kinda kill the performance and data locality too, so you need something smart closer to "materialised SQL views" to get performance.
> How is having a struct dissimilar to having an object iterated, especially with C++ essentially having barely any difference between a struct and a class?
I never said it was. I just said that merely using a "class" doesn't make something an OOP pattern, especially if the implementor has no choice over which programming feature to use.
- kaba0 5y agoThanks for the details! Though wouldn’t using arrays of structs kill the performance the same way as array of objects do (stack-allocated ones)? So, one would essentially have to have a SOA, or — the OOP abstraction: a class of arrays that enclose this hot loop of code, making the implementation opaque to a calling code.
- ratww 5y ago> Though wouldn’t using arrays of structs kill the performance the same way as array of objects do (stack-allocated ones)? Not really. Components are long-lived so they're not allocated on the stack. And contiguous arrays of structs/objects is the best case for cache locality, that's the entire performance case of ECS.
- kaba0 5y agoA simple struct/object having in order an int, a string pointer and another int having 3 different things happening to them can in some case be worse than having all the ints next to each other, etc. ISIISI… vs III…SSS…III.. So for cache locality the latter is the best option.
- meheleventyone 5y agoBest way to think about ECS is a generic pattern to help make things data oriented. It’s not necessarily going to be optimal though. It’s SoA over the Entity rather than individual struct members which might in a more tuned setup be more performant. This is also where ECS as a pattern falls down (from the simplistic ideas about them being performant) because keeping components in packed arrays is only one part of making them efficient. The biggest issue is making sure your entity data is best organised for the most common data access patterns. For example you can’t actually store data in big blocks of single component type but need to consider the shapes/archetypes (common sets of components) that make up an Entity. For each archetype we can store the components packed in arrays so that they can be iterated contiguously. That way Systems can visit all of the archetypes that contain the components they care about and iterate straight through them whilst minimising cache misses. This approach obviously falls down the more heterogeneous your Entities are. It also incurs a cost when a component is added or removed from an Entity so makes some common ECS patterns more expensive. There are other approaches with different trade offs. But this is also pretty academic for most games which don’t have the entity count or gameplay complexity to actually require this level of performance anxiety.
- ratww 5y agoNot really. There's no silver bullet when it comes to AoS or SoA. If you have a pair of integers, A and B, that are supposed to be always read/write together, the ABABAB of ECS beats AAA...BBB in terms of cache locality, hands down. The advantage of ECS in this case is that it enforces data organisation to be coherent to the way data is used. All this is mentioned on the seminal articles about Data-oriented Design, including the ones that popularised the terms AoS and SoA, and in lots of literature about modern ECS. I suggest looking up what Entities and Components mean in ECS. It is doing all those things you're thinking of, but in a more optimal way.