MonoBehaviourTree icon indicating copy to clipboard operation
MonoBehaviourTree copied to clipboard

GC.Alloc every frame

Open laicasaane opened this issue 6 months ago • 2 comments

Today I do a profiling and notice that the current usage of Variable<T>.AddListener and .RemoveListener causes at least 4 allocations every frame.


Each of these methods creates 1 allocation. 1 delegate instance is created out of OnVariableChange.

// IsSetCondition.cs
// NumberCondition.cs

public override void OnAllowInterrupt()
{
    [...] .GetVariable().AddListener(OnVariableChange);
}

public override void OnDisallowInterrupt()
{
    [...] .GetVariable().RemoveListener(OnVariableChange);
}

To eliminate these, we can just cache the delegate instances in private fields and use them instead.

public class IsSetCondition : Condition
{
    private readonly ChangeListener<bool> _boolListener;
    private readonly ChangeListener<GameObject> _gameObjectListener;
    private readonly ChangeListener<Transform> _transformListener;

    public IsSetCondition()
    {
        _boolListener = OnVariableChange;
        _gameObjectListener = OnVariableChange;
        _transformListener = OnVariableChange;
    }

    public override void OnAllowInterrupt()
    {
        [...] .GetVariable().AddListener(_boolListener);
    }
}

Each of these also creates another allocation.

// Variable.cs

public void AddListener(ChangeListener<T> listener)
{
    listeners += listener;
}

public void RemoveListener(ChangeListener<T> listener)
{
    listeners -= listener;
}

I haven't understood the logic of Variable<T>.listeners so I can't propose a solution for now.

laicasaane avatar Aug 22 '24 05:08 laicasaane