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

View File

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

View File

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

View File

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