我有一个数据类型,其生命周期未定义。因此它是一个类。但是,它被创建得非常频繁,这导致它不断分配内存。它还具有相当大的权重,这使其存在问题。
怎样才能减少此数据类型所需的分配次数,优化其分配和释放,并减少 GC 压力?(创建结构是行不通的,因为它需要不断复制数据,并且不可能始终能够通过 try-finally 从内部数组中释放数据)。
[Serializable]
public class DamageData
{
[Serializable]
public class DamageDataInternal
{
public float[] values;
public float totalDamage;
public int cachedHashCode;
public bool isHashCodeDirty;
}
private DamageDataInternal _internalData;
public static readonly DamageType[] DamageTypes;
public int Hash => GetHashCode();
public bool IsInit => _internalData != null;
static DamageData()
{
DamageTypes = (DamageType[])Enum.GetValues(typeof(DamageType));
}
~DamageData()
{
DamageDataInternalPool.Shared.Release(_internalData);
_internalData = null;
}
public DamageData()
{
_internalData = DamageDataInternalPool.Shared.Get();
_internalData.totalDamage = 0f;
_internalData.isHashCodeDirty = true;
_internalData.cachedHashCode = 0;
}
}
using UnityEngine.Pool;
public class DamageDataInternalPool
{
private readonly ObjectPool<DamageData.DamageDataInternal> _pool;
public static DamageDataInternalPool Shared { get; } = new();
public DamageDataInternalPool()
{
_pool = new ObjectPool<DamageData.DamageDataInternal>(
createFunc: () => new DamageData.DamageDataInternal(),
actionOnGet: obj =>
{
obj.totalDamage = default;
obj.cachedHashCode = default;
obj.isHashCodeDirty = default;
obj.values = ArrayPool<float>.Shared.Rent(DamageData.DamageTypes.Length);
for (var i = 0; i < DamageData.DamageTypes.Length; i++)
{
obj.values[i] = 0f;
}
},
actionOnRelease: obj =>
{
ArrayPool<float>.Shared.Return(obj.values);
},
actionOnDestroy: null,
defaultCapacity: 10,
maxSize: 10000
);
}
public DamageData.DamageDataInternal Get()
{
return _pool.Get();
}
public void Release(DamageData.DamageDataInternal obj)
{
_pool.Release(obj);
}
}
我尝试将其内部数据封装在一个单独的类中,并通过对象池获取该类的实例,这样主类的权重应该仅为 SIZE_OF_LINK + SOME_META_DATA_SIZE。然而,这似乎根本没有改变这种情况,仍然有大量分配。