Post Processing HasComponent away

Currently SystemBase code like this:

Entities.ForEach( ( Entity ent, ref MapUnitColor mapUnitColor, in ApplyColorBasedUponUsability colouring ) =>
{
    mapUnitColor.Value = HasComponent<IsUsable>( ent ) ? colorBasedUponUsability.UsableColor : colorBasedUponUsability.NotUsableColor;
}).Run();

Results in code like this:

[MethodImpl(MethodImplOptions.NoInlining)]
public void IterateEntities(ref ArchetypeChunk chunk, [NoAlias] ref LambdaParameterValueProviders.Runtimes runtimes)
{
    int count = chunk.Count;
    for (int i = 0; i < count; i++)
    {
        OriginalLambdaBody(runtimes.runtime_ent.For(i), ref runtimes.runtime_color.For(i), in runtimes.runtime_colouring.For(i));
    }
}

private void OriginalLambdaBody(Entity ent, ref MapUnitColor mapUnitColor, in ApplyColorBasedUponUsability colorBasedUponUsability)
{
    mapUnitColor.Value = (_ComponentDataFromEntity_IsUsable_0.HasComponent(ent) ? colorBasedUponUsability.UsableColor : colorBasedUponUsability.NotUsableColor);
}

Currently everytime we call the OriginalLamdaBody we check if the entity we iterate upon has the component.
Wouldn’t it be possible to do a chunk based lookup and branch upon that inside the IterateEntities method?

Is the performance gain we would get from that negligible?
Or am i just missing something?

You’re correct. It also uses CDFE rather than chunk.exists - possibly rand access calls when they don’t need to be (I’m not entirely sure). It’s a cost to be aware of and imo one of the main reasons to still consider using the much more verbose IJobChunk if you have something like this is in the hot path. That said, the difference can be fairly negligible depending on number of entities, density of chunks etc. There have been mentions of a possible Chunk.ForEach API or similar to help with this ( Lambdas & Optional ICDs ) - but that was a long time ago so I’m not expecting anything soon.

1 Like

The other alternative is to use two ForEach loops like this:

Entities.WithAll<IsUsable>().ForEach( ( ref MapUnitColor mapUnitColor, in ApplyColorBasedUponUsability colouring ) =>
{
    mapUnitColor.Value = colorBasedUponUsability.UsableColor ;
}).Run();

Entities.WithNone<IsUsable>().ForEach( ( ref MapUnitColor mapUnitColor, in ApplyColorBasedUponUsability colouring ) =>
{
    mapUnitColor.Value = colorBasedUponUsability.NotUsableColor ;
}).Run();
3 Likes