ECS Struct functions

Is there a performance penalty when calling a function on an IComponentData struct inside a job?

Like this:

public struct MyStruct : IComponentData
    {
        public float2 MyValue { get; set; }
    
        public Translation MyMethod(Translation target, float deltaTime)
        {
            target.Value = new float2(target.Value.x + MyValue.x * deltaTime, target.Value.y + MyValue.y * deltaTime);
            return target;
        }
    }

For those that are curious. I am trying to find an efficient way to write generic systems.

Depends where you are calling it from I guess?

Compared to using jobs? Yes. You are doing random access in memory and don’t get the benefits of Burst compilation.

So any kind of function call on a struct inside a job is going to make a random memory access?

And does the same rules apply for the get/set properties?

I’m not sure about it. Anyway you could use:
[MethodImpl(MethodImplOptions.AggressiveInlining)]

public struct MyStruct : IComponentData
    {
        public float2 MyValue { get; set; }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Translation MyMethod(Translation target, float deltaTime)
        {
            target.Value = new float2(target.Value.x + MyValue.x * deltaTime, target.Value.y + MyValue.y * deltaTime);
            return target;
        }
    }

No, it usually won’t. Small functions will probably be inlined; getters and setters will almost certainly be inlined and completely vanish. That said, bigger functions might not get inlined and in those cases you might get a bit of jumping around in memory to fetch that code, but this should in most cases not be a problem. The problematic cases are usually about data that is scattered randomly in memory, not code. (Of course there are also cases where this is the problem but I’m willing to bet that your case it not one of them.) Honestly, I don’t think there is a blanket statement that covers all cases: In a tight loop you might pay a big penalty if a function is not inlined, in other places it might not matter at all.

I’d suggest working with the hypothesis that calling small functions is usually not a problem and then go ahead and measure the actual cases you are interested in.

You should not have mutating methods in an IComponentData. That’s an OOP way of thinking about it. You can maybe get by with simple mutating properties as long as the API is intuitive. But even then, the use cases where that makes sense are rare. Definitely not your use case.

1 Like