I have a situation where I have a producer system that creates signals that later get picked up by a consumer system. These signals contain some data that the consumer system uses for its execution.
I currently see two good ways of doing this:
The producer system creates signal entities, that get picked up by the consumer system. These signal entities contain the required data in a component. The consumer system processes the signal entities in a job going over the entities (like Entities.ForEach, or the new foreach).
The producer system accesses a persistent NativeContainer (like a NativeList), and adds the signals as structs into this container. The consumer system then loops over the signals container in a job (like Job.WithCode).
It seems to me that the second solution would be better for performance, as it does not require any cost of structural changes (entity creation, deletion). I also assume that looping over the elements of a nativecontainer is faster than the foreach looping over entities, but I might be wrong there.
My question here is which of these solutions would be better, and what the considerations for both solutions are.
In isolation, producing the data you need directly into a container and then consuming that container in another job will have the least overhead. It sounds like you are just using entities as an index for the data produced and then consumed by another system, if so then the creation of entities will add some more overhead than if you used a NativeContainer directly. As well, getting component data from chunk memory itself needs to be looked up so there is some overhead there as well before we can start iterating over each entity’s component data. However if you intend to use the entities for other queries and/or data mapping outside of this producer consumer scenario then you might still want to do the first option.
If you create all entities at once in the producer system, the components you want to write into / produce for each entity will all be contiguous just like if you used a NativeList, with the exception that entities in chunk memory are segregated in 128 entities at a time. If you have thousands of items/entities you are hoping to produce, you will see some overhead from walking ECS chunk memory compared to a completely contiguous native allocation that you’d get with NativeList/NativeArray etc…