Search Unity

Iterating Over Entities in Multiple Chunks

Discussion in 'Data Oriented Technology Stack' started by orionburcham, Dec 17, 2018.

  1. orionburcham

    orionburcham

    Joined:
    Jan 31, 2010
    Posts:
    491
    I need to verify my understanding of how Unity organizes Chunks in memory. Would the following all be true?

    1. In Unity ECS, Chunks are blocks of memory which store the Component Data, for entities of the same archetype (which all have the same components).

    2. Adding or removing a Component from an entity changes the entity’s archetype. This will always cause Unity to move the entity’s Components to a different Chunk in memory.

    3. Moving entities between Chunks May mean expanding or shrinking the chunk. This is all managed automatically by Unity.

    - - -

    Here’s the part I’m confused about:

    4. A System can request a collection of entities that all have the specified component types. ***This will return all entities with the specified component types, EVEN IF some of those entities have other component types which are NOT in common.***

    - - -

    If #4 is true, then that would mean a System may often be iterating over entities of different archetypes, which therefore exist in different chunks of memory. That would eliminate the sequential reading of memory, from which ECS derives its largest perf benefit. CPU cache misses seem like they would be unavoidable, and potentially very frequent.

    Thanks to anyone who can verify what I’ve written here, or tell me what I’m misunderstanding. :)
     
    Last edited: Dec 17, 2018
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,559
    Chunk size is fixed at 16K

    Are you talking about injecting ComponentDataArray? This is depreciated and this is pretty much the reason why.

    You should be using chunk iteration which will maintain memory performance.
     
  3. orionburcham

    orionburcham

    Joined:
    Jan 31, 2010
    Posts:
    491
    Good to know about the fixed Chunk size- thanks!

    - - -

    Just to make sure I understand your second point correctly: Are you saying that If I have three Component types:

    - A
    - B
    - C

    ...and three entities with the following component configurations:

    Entity 0: A, B
    Entity 1: B
    Entity 2: B, C

    ...that Unity ECS won't let me write a single System that iterates over the 'B' component of each of these entities?
     
    Last edited: Dec 17, 2018
  4. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,261
    You will be iterating over 3 chunks of 1 entity each in that case. In each chunk you will work on a NativeArray<B> of length 1.
     
  5. orionburcham

    orionburcham

    Joined:
    Jan 31, 2010
    Posts:
    491
    Wouldn’t that case cause 3 cache misses?

    3 cache misses is certainly tiny, but what about iterating over every different kind of entity with a Position Component?

    - - -

    The other reason I ask, is that I’ve heard Joachim and one other unity dev recommend adding components to an entity as a way of sending messages. Reactive systems would then catch those new components and respond to them.

    But that could seriously cut down on archetype cohesion. Imagine if you had 200 entities which originally only had a ‘B’ component. Now, one update later, 10% could also have a ‘D’ component, and 10% more might have an ‘E’, etc. the types or numbers of permutations could be large and unpredictable.

    - - -

    And then there’s any system which needs to access Components from a foreign entity (one that’s not in the current iteration group). For example, each entity you’re currently iterating over might need to check some component data of a separate, ‘target’ entity.

    - - -

    It seems like all of those things would cause cache misses, and all of them are pretty common situations in game code.

    Should I not be using Unity ECS unless my game features thousands of similar objects, without much interaction between entities (like in Unity’s recent demos)?
     
    Last edited: Dec 17, 2018
  6. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,261
    It would cause 3 misses because CPU cannot prefetch. With the same chunk it can prefetch equal to cache line size while you are working on the current item. (64 bytes per line?)

    ECS's memory scheme certainly at its worst when you have like 1 or small entity number per archetype and many archetypes. If you have more than 1 entity in the archetype it is still better than full OOP, since that should be non contiguous at all in common iteration over the same class instances.

    For tagging it is not just causing cache miss, you also get the ability to selecting only the chunk you want to work on with ECS chunk query. It is like you get a dynamic grouping system automatically rather than maintaining your own or iterating through all items and use `if` to find the item to work on. Maybe you could benefit from that still.

    And still ECS provides good interfacing to C# jobs that make it possible to use the previously idle worker threads. Without ECS you would be copying data for the job to work on.

    Also if you need faster iteration through all B component you should prepare your own NativeArray<B> collected from chunks so they have no chunk borders and became contiguous, depending if it worths or not.
     
    Last edited: Dec 17, 2018
    florianhanke likes this.
  7. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,369
  8. orionburcham

    orionburcham

    Joined:
    Jan 31, 2010
    Posts:
    491
    I really shouldn't be so curmudgeonly. Ultimately I'm a huge fan of ECS, and want it to succeed. I want these problems to be solved, and I'm thrilled that such a force of talented engineers like Unity is taking on such difficult problems.

    I want to keep in mind that it's still very early days for Unity ECS, and there will be time to address some concerns.

    For my part, I will settle in for the ride, and work as hard as I can to adopt their approach. I also want to find ways to apply some of the benefits I love from event-driven code to an ECS architecture.
     
  9. Jay-Pavlina

    Jay-Pavlina

    Joined:
    Feb 19, 2012
    Posts:
    195
    I think I may have misunderstood something. Do entities exist in one chunk at a time only or can they exist in multiple chunks? In this example:

    Entity 0: A, B
    Entity 1: B
    Entity 2: B, C

    I thought entities 0, 1, 2 would all exist in a chunk with B, but they would also be in their separate chunks. I guess I am wrong?
     
  10. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,559
    They only exist in a single chunk at a time. You'd have 3 separate chunks for that case with 1 entity in each.
     
    Jay-Pavlina likes this.
  11. orionburcham

    orionburcham

    Joined:
    Jan 31, 2010
    Posts:
    491
    Like tertle said, each entity’s Components are only in a single chunk. :)

    If there was a copy in multiple chunks, you’d have to figure out how to propegate changes across all the copies. Besides being odd, that would break the pattern of linearly reading memory, which lets Unity take advantage of CPU prefetching.
     
  12. Jay-Pavlina

    Jay-Pavlina

    Joined:
    Feb 19, 2012
    Posts:
    195
    It would make linearly reading memory faster if you read from the right chunk because the data would be contiguous, but copying the data would be too slow, and so it makes sense that it is not done that way.