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.
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://discussions.unity.com/t/702049/18
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?
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.
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!