So reduzieren Sie die Speicherzuweisung für Datentypen, deren Lebensdauer nicht definiert ist
Posted: 13 Jan 2025, 20:04
Ich habe einen Datentyp, dessen Lebensdauer undefiniert ist. Daher ist es eine Klasse. Allerdings wird es sehr oft erstellt, was dazu führt, dass es ständig Speicher belegt. Es hat auch ziemlich viel Gewicht, was es problematisch macht.
Was kann getan werden, um die Anzahl der für diesen Datentyp erforderlichen Zuweisungen zu reduzieren, seine Zuweisungen und Freigaben zu optimieren und GC zu reduzieren? Druck? (Das Erstellen einer Struktur würde nicht funktionieren, da dies ein ständiges Kopieren von Daten erfordern würde und es unmöglich wäre, Daten immer über try-finally aus dem internen Array freizugeben.)
Ich habe versucht, die internen Daten in einer separaten Klasse zu kapseln, von denen ich Instanzen über Objektpooling erhalte, sodass die Hauptklasse nur SIZE_OF_LINK + SOME_META_DATA_SIZE wiegen sollte. Allerdings scheint sich dadurch an der Situation überhaupt nichts geändert zu haben und es gibt immer noch viel Zuteilung.
Was kann getan werden, um die Anzahl der für diesen Datentyp erforderlichen Zuweisungen zu reduzieren, seine Zuweisungen und Freigaben zu optimieren und GC zu reduzieren? Druck? (Das Erstellen einer Struktur würde nicht funktionieren, da dies ein ständiges Kopieren von Daten erfordern würde und es unmöglich wäre, Daten immer über try-finally aus dem internen Array freizugeben.)
Code: Select all
[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;
}
}
Code: Select all
using UnityEngine.Pool;
public class DamageDataInternalPool
{
private readonly ObjectPool _pool;
public static DamageDataInternalPool Shared { get; } = new();
public DamageDataInternalPool()
{
_pool = new ObjectPool(
createFunc: () => new DamageData.DamageDataInternal(),
actionOnGet: obj =>
{
obj.totalDamage = default;
obj.cachedHashCode = default;
obj.isHashCodeDirty = default;
obj.values = ArrayPool.Shared.Rent(DamageData.DamageTypes.Length);
for (var i = 0; i < DamageData.DamageTypes.Length; i++)
{
obj.values[i] = 0f;
}
},
actionOnRelease: obj =>
{
ArrayPool.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);
}
}