优化Object Pool 1.优化GC 2.优化每热路径 3.旧代码删除

This commit is contained in:
陈思海 2026-03-26 17:53:07 +08:00
parent 13af026251
commit 1690ac7005
4 changed files with 54 additions and 96 deletions

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using AlicizaX;
namespace AlicizaX.ObjectPool
@ -139,6 +140,8 @@ namespace AlicizaX.ObjectPool
/// <returns>所有对象信息。</returns>
public abstract ObjectInfo[] GetAllObjectInfos();
public abstract void GetAllObjectInfos(List<ObjectInfo> results);
internal abstract void Update(float elapseSeconds, float realElapseSeconds);
internal abstract void Shutdown();

View File

@ -157,8 +157,8 @@ namespace AlicizaX.ObjectPool
/// </summary>
public void Unspawn()
{
m_Object.OnUnspawn();
m_Object.LastUseTime = DateTime.UtcNow;
m_Object.OnUnspawn();
m_SpawnCount--;
if (m_SpawnCount < 0)
{

View File

@ -14,10 +14,8 @@ namespace AlicizaX.ObjectPool
{
private readonly GameFrameworkMultiDictionary<string, Object<T>> m_Objects;
private readonly Dictionary<object, Object<T>> m_ObjectMap;
private readonly ReleaseObjectFilterCallback<T> m_DefaultReleaseObjectFilterCallback;
private readonly List<Object<T>> m_CachedCanReleaseObjects;
private readonly List<Object<T>> m_CachedToReleaseObjects;
private readonly List<T> m_CachedCanReleaseTargets;
private readonly IComparer<Object<T>> m_ReleaseObjectComparer;
private readonly bool m_AllowMultiSpawn;
private float m_AutoReleaseInterval;
@ -40,10 +38,8 @@ namespace AlicizaX.ObjectPool
{
m_Objects = new GameFrameworkMultiDictionary<string, Object<T>>();
m_ObjectMap = new Dictionary<object, Object<T>>();
m_DefaultReleaseObjectFilterCallback = DefaultReleaseObjectFilterCallback;
m_CachedCanReleaseObjects = new List<Object<T>>();
m_CachedToReleaseObjects = new List<Object<T>>();
m_CachedCanReleaseTargets = new List<T>();
m_ReleaseObjectComparer = Comparer<Object<T>>.Create(ReleaseObjectComparer);
m_AllowMultiSpawn = allowMultiSpawn;
m_AutoReleaseInterval = autoReleaseInterval;
@ -76,8 +72,14 @@ namespace AlicizaX.ObjectPool
{
get
{
GetCanReleaseObjects(m_CachedCanReleaseObjects);
return m_CachedCanReleaseObjects.Count;
int count = 0;
foreach (KeyValuePair<object, Object<T>> kv in m_ObjectMap)
{
Object<T> obj = kv.Value;
if (!obj.IsInUse && !obj.Locked && obj.CustomCanReleaseFlag)
count++;
}
return count;
}
}
@ -405,7 +407,7 @@ namespace AlicizaX.ObjectPool
/// </summary>
public override void Release()
{
Release(Count - m_Capacity, m_DefaultReleaseObjectFilterCallback);
ReleaseWithDefaultFilter(Count - m_Capacity);
}
/// <summary>
@ -414,7 +416,7 @@ namespace AlicizaX.ObjectPool
/// <param name="toReleaseCount">尝试释放对象数量。</param>
public override void Release(int toReleaseCount)
{
Release(toReleaseCount, m_DefaultReleaseObjectFilterCallback);
ReleaseWithDefaultFilter(toReleaseCount);
}
/// <summary>
@ -434,11 +436,6 @@ namespace AlicizaX.ObjectPool
public void Release(int toReleaseCount, ReleaseObjectFilterCallback<T> releaseObjectFilterCallback)
{
if (releaseObjectFilterCallback == null)
{
throw new GameFrameworkException("Release object filter callback is invalid.");
}
if (releaseObjectFilterCallback == m_DefaultReleaseObjectFilterCallback)
{
ReleaseWithDefaultFilter(toReleaseCount);
return;
@ -457,13 +454,13 @@ namespace AlicizaX.ObjectPool
m_AutoReleaseTime = 0f;
GetCanReleaseObjects(m_CachedCanReleaseObjects);
m_CachedCanReleaseTargets.Clear();
List<T> candidateTargets = new List<T>(m_CachedCanReleaseObjects.Count);
foreach (Object<T> internalObject in m_CachedCanReleaseObjects)
{
m_CachedCanReleaseTargets.Add(internalObject.Peek());
candidateTargets.Add(internalObject.Peek());
}
List<T> toReleaseObjects = releaseObjectFilterCallback(m_CachedCanReleaseTargets, toReleaseCount, expireTime);
List<T> toReleaseObjects = releaseObjectFilterCallback(candidateTargets, toReleaseCount, expireTime);
if (toReleaseObjects == null || toReleaseObjects.Count <= 0)
{
return;
@ -495,6 +492,18 @@ namespace AlicizaX.ObjectPool
public override ObjectInfo[] GetAllObjectInfos()
{
List<ObjectInfo> results = new List<ObjectInfo>();
GetAllObjectInfos(results);
return results.ToArray();
}
public override void GetAllObjectInfos(List<ObjectInfo> results)
{
if (results == null)
{
throw new GameFrameworkException("Results is invalid.");
}
results.Clear();
foreach (KeyValuePair<string, GameFrameworkLinkedListRange<Object<T>>> objectRanges in m_Objects)
{
foreach (Object<T> internalObject in objectRanges.Value)
@ -502,8 +511,6 @@ namespace AlicizaX.ObjectPool
results.Add(new ObjectInfo(internalObject.Name, internalObject.Locked, internalObject.CustomCanReleaseFlag, internalObject.Priority, internalObject.LastUseTime, internalObject.SpawnCount));
}
}
return results.ToArray();
}
internal override void Update(float elapseSeconds, float realElapseSeconds)
@ -529,7 +536,6 @@ namespace AlicizaX.ObjectPool
m_ObjectMap.Clear();
m_CachedCanReleaseObjects.Clear();
m_CachedToReleaseObjects.Clear();
m_CachedCanReleaseTargets.Clear();
}
private Object<T> GetObject(object target)
@ -566,10 +572,7 @@ namespace AlicizaX.ObjectPool
return false;
}
if (!m_Objects.Remove(internalObject.Name, internalObject.NameNode))
{
m_Objects.Remove(internalObject.Name, internalObject);
}
m_Objects.Remove(internalObject.Name, internalObject.NameNode);
internalObject.NameNode = null;
m_ObjectMap.Remove(targetObject.Target);
@ -656,45 +659,6 @@ namespace AlicizaX.ObjectPool
}
}
private List<T> DefaultReleaseObjectFilterCallback(List<T> candidateObjects, int toReleaseCount, DateTime expireTime)
{
m_CachedCanReleaseTargets.Clear();
if (expireTime > DateTime.MinValue)
{
for (int i = candidateObjects.Count - 1; i >= 0; i--)
{
if (candidateObjects[i].LastUseTime <= expireTime)
{
m_CachedCanReleaseTargets.Add(candidateObjects[i]);
candidateObjects.RemoveAt(i);
continue;
}
}
toReleaseCount -= m_CachedCanReleaseTargets.Count;
}
for (int i = 0; toReleaseCount > 0 && i < candidateObjects.Count; i++)
{
for (int j = i + 1; j < candidateObjects.Count; j++)
{
if (candidateObjects[i].Priority > candidateObjects[j].Priority
|| candidateObjects[i].Priority == candidateObjects[j].Priority && candidateObjects[i].LastUseTime > candidateObjects[j].LastUseTime)
{
T temp = candidateObjects[i];
candidateObjects[i] = candidateObjects[j];
candidateObjects[j] = temp;
}
}
m_CachedCanReleaseTargets.Add(candidateObjects[i]);
toReleaseCount--;
}
return m_CachedCanReleaseTargets;
}
private static int ReleaseObjectComparer(Object<T> a, Object<T> b)
{
int priorityCompare = a.Priority.CompareTo(b.Priority);

View File

@ -16,6 +16,7 @@ namespace AlicizaX.ObjectPool
private const int DefaultPriority = 0;
private readonly Dictionary<TypeNamePair, ObjectPoolBase> m_ObjectPools;
private readonly List<ObjectPoolBase> m_ObjectPoolList;
private readonly List<ObjectPoolBase> m_CachedAllObjectPools;
private readonly Comparison<ObjectPoolBase> m_ObjectPoolComparer;
@ -25,6 +26,7 @@ namespace AlicizaX.ObjectPool
public ObjectPoolService()
{
m_ObjectPools = new Dictionary<TypeNamePair, ObjectPoolBase>();
m_ObjectPoolList = new List<ObjectPoolBase>();
m_CachedAllObjectPools = new List<ObjectPoolBase>();
m_ObjectPoolComparer = ObjectPoolComparer;
}
@ -50,9 +52,9 @@ namespace AlicizaX.ObjectPool
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
void IServiceTickable.Tick(float deltaTime)
{
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
for (int i = 0; i < m_ObjectPoolList.Count; i++)
{
objectPool.Value.Update(Time.deltaTime,Time.unscaledDeltaTime);
m_ObjectPoolList[i].Update(deltaTime, Time.unscaledDeltaTime);
}
}
@ -63,12 +65,13 @@ namespace AlicizaX.ObjectPool
protected override void OnDestroyService()
{
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
for (int i = 0; i < m_ObjectPoolList.Count; i++)
{
objectPool.Value.Shutdown();
m_ObjectPoolList[i].Shutdown();
}
m_ObjectPools.Clear();
m_ObjectPoolList.Clear();
m_CachedAllObjectPools.Clear();
}
@ -146,9 +149,9 @@ namespace AlicizaX.ObjectPool
throw new GameFrameworkException("Condition is invalid.");
}
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
for (int i = 0; i < m_ObjectPoolList.Count; i++)
{
if (condition(objectPool.Value))
if (condition(m_ObjectPoolList[i]))
{
return true;
}
@ -231,11 +234,11 @@ namespace AlicizaX.ObjectPool
throw new GameFrameworkException("Condition is invalid.");
}
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
for (int i = 0; i < m_ObjectPoolList.Count; i++)
{
if (condition(objectPool.Value))
if (condition(m_ObjectPoolList[i]))
{
return objectPool.Value;
return m_ObjectPoolList[i];
}
}
@ -255,11 +258,11 @@ namespace AlicizaX.ObjectPool
}
List<ObjectPoolBase> results = new List<ObjectPoolBase>();
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
for (int i = 0; i < m_ObjectPoolList.Count; i++)
{
if (condition(objectPool.Value))
if (condition(m_ObjectPoolList[i]))
{
results.Add(objectPool.Value);
results.Add(m_ObjectPoolList[i]);
}
}
@ -284,11 +287,11 @@ namespace AlicizaX.ObjectPool
}
results.Clear();
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
for (int i = 0; i < m_ObjectPoolList.Count; i++)
{
if (condition(objectPool.Value))
if (condition(m_ObjectPoolList[i]))
{
results.Add(objectPool.Value);
results.Add(m_ObjectPoolList[i]);
}
}
}
@ -320,25 +323,13 @@ namespace AlicizaX.ObjectPool
{
if (sort)
{
List<ObjectPoolBase> results = new List<ObjectPoolBase>();
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
{
results.Add(objectPool.Value);
}
List<ObjectPoolBase> results = new List<ObjectPoolBase>(m_ObjectPoolList);
results.Sort(m_ObjectPoolComparer);
return results.ToArray();
}
else
{
int index = 0;
ObjectPoolBase[] results = new ObjectPoolBase[m_ObjectPools.Count];
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
{
results[index++] = objectPool.Value;
}
return results;
return m_ObjectPoolList.ToArray();
}
}
@ -355,10 +346,7 @@ namespace AlicizaX.ObjectPool
}
results.Clear();
foreach (KeyValuePair<TypeNamePair, ObjectPoolBase> objectPool in m_ObjectPools)
{
results.Add(objectPool.Value);
}
results.AddRange(m_ObjectPoolList);
if (sort)
{
@ -1245,6 +1233,7 @@ namespace AlicizaX.ObjectPool
ObjectPool<T> objectPool = new ObjectPool<T>(name, allowMultiSpawn, autoReleaseInterval, capacity, expireTime, priority);
m_ObjectPools.Add(typeNamePair, objectPool);
m_ObjectPoolList.Add(objectPool);
return objectPool;
}
@ -1269,6 +1258,7 @@ namespace AlicizaX.ObjectPool
Type objectPoolType = typeof(ObjectPool<>).MakeGenericType(objectType);
ObjectPoolBase objectPool = (ObjectPoolBase)Activator.CreateInstance(objectPoolType, name, allowMultiSpawn, autoReleaseInterval, capacity, expireTime, priority);
m_ObjectPools.Add(typeNamePair, objectPool);
m_ObjectPoolList.Add(objectPool);
return objectPool;
}
@ -1278,6 +1268,7 @@ namespace AlicizaX.ObjectPool
if (m_ObjectPools.TryGetValue(typeNamePair, out objectPool))
{
objectPool.Shutdown();
m_ObjectPoolList.Remove(objectPool);
return m_ObjectPools.Remove(typeNamePair);
}