Search Unity

Good practice around Components quantity and size

Discussion in 'Entity Component System' started by dzamani, Nov 14, 2019.

  1. dzamani

    dzamani

    Joined:
    Feb 25, 2014
    Posts:
    122
    Hello,

    I think no one asked this before (since I found nothing directly related to these questions on the forum), so here are my questions:
    • Is there any downside or limit on the number of components on the same entity ?
    • Is there a limit on the size of a component ? (I've seen people talking about the size needed to be under 100 bytes)
    Thanks!

    PS: I'm only talking about IComponentData and not regular Unity components obviously
     
    Last edited: Nov 14, 2019
  2. felipin

    felipin

    Joined:
    Nov 18, 2015
    Posts:
    49
    dzamani likes this.
  3. Justin_Larrabee

    Justin_Larrabee

    Joined:
    Apr 24, 2018
    Posts:
    106
    Chunks are currently 16 kilobytes, so the larger your entity is the fewer that fit in a chunk. That would put a hard cap of 16 kilobytes on the size of an entity. DynamicBuffer can alleviate that pressure with a basically unlimited size cap (gigabytes if you are a crazy person).

    IJobForEach dispatches across cores per-chunk, so in some scenarios you actually want fewer entities in a chunk. In general though, fit as many as you can in a single chunk for the best performance.
     
    dzamani likes this.
  4. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Just making sure I understand this correctly:

    If I have these entities:
    Would that result in:
    I'm guessing it's not result B because then every single entity that has at least a Translation component would end up in the same chunk?
     
    Last edited: Nov 14, 2019
  5. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    Yes, it will be option A.

    *Edit: Wrong answer.

    []'s
     
    Last edited: Nov 14, 2019
  6. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    Actually, as today, it's less than 16kb with 256b reserved as a header.
    They have stated that, in the future, the chunk size could be configurable.
    https://forum.unity.com/threads/ecs-memory-layout.532028/#post-4219489

    []'s
     
  7. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    So if this is happening:
    How does an IJobChunk launched with an EntityQuery{ All = Translation, Rotation } decide whether to choose Chunk1 or Chunk2? We can check for optional components in IJobChunks, so does that mean it'll iterate both on Chunk1 and Chunk2?

    And if it iterates on both, how does it avoid modifying the same data twice?
     
  8. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    Sorry, I just misread.
    Entities are not shared between chunks. In your case each entity will be in a different chunk.

    []'s
     
    dzamani and PhilSA like this.
  9. Radu392

    Radu392

    Joined:
    Jan 6, 2016
    Posts:
    210
    In an IJobChunk, you only get the necessary components you need for that particular job, not the whole entity with all of its components, because you specify the ArchetypeChunkComponentType. I imagine IJobForEach would be similar.

    So if you have entities with 100 components, each with a single float3 in them, and a job that requires 5 of these components, the resulting chunk will only consist of 5 float3s. In that case, it's better than to have 5 components with 20 float3's each.


    Edit: Clarification: The resulting chunk will then only consist of a large number of entities because it needs only 5 float3s. Whereas if entities had 5 components with 20 float3s each, then the resulting chunk would have a lower number of entities due to more data being passed in. So the way I understand it is that there are as many chunk types as there are job types.

    Right?
     
    Last edited: Nov 14, 2019
    PhilSA likes this.
  10. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    A chunk contains exactly one archetype. So in this example:
    • EntityA
      • Translation
      • Rotation
      • Scale
    • EntityB
      • Translation
      • Rotation
    • EntityC
      • MyAIController
    • EntityD
      • Translation
      • Rotation

    EntityA would exist in ChunkA, which has a header and an array of Translation, Rotation, and Scale components.

    EntityB would exist in ChunkB, which has a header and an array of Translation and Rotation components. These arrays are slightly larger than ChunkA.

    EntityC would exist in ChunkC, which has a header and an array of MyAIController components.

    EntityD would exist in ChunkB, as its archetype exactly matches EntityB.

    An IJobForEach<Translation, Rotation> would iterate over both ChunkA and ChunkB, as their archetypes both fulfill the underlying EntityQuery. The Scale array in ChunkA would not be touched.

    An IJobChunk could use an EntityQuery for just the Translation component, but have ArchetypeChunkComponentTypes for Rotation and Scale. It can then check whether or not the active chunk has those additional components and do selective logic appropriately. The Transform system does this. Some of my own code does this as well. It is crazy powerful!
     
    dzamani, Radu392 and PhilSA like this.