add gc-like clearing of deleted entities

This commit is contained in:
Mikhail 2023-11-22 11:53:41 +08:00
parent de88b0a8dd
commit 5e6ac8cb16
4 changed files with 27 additions and 6 deletions

View File

@ -12,14 +12,17 @@ namespace DCFApixels.DragonECS
public SystemsLayerMarkerSystem(string name) => this.name = name;
}
[DebugHide, DebugColor(DebugColor.Grey)]
public class DeleteEmptyEntitesSystem : IEcsRunProcess, IEcsInject<EcsWorld>
public class EndFrameSystem : IEcsRunProcess, IEcsInject<EcsWorld>
{
private List<EcsWorld> _worlds = new List<EcsWorld>();
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
public void Inject(EcsWorld obj) => _worlds.Add(obj);
public void Run(EcsPipeline pipeline)
{
foreach (var world in _worlds)
{
world.DeleteEmptyEntites();
world.ReleaseDelEntityBuffer();
}
}
}
[DebugHide, DebugColor(DebugColor.Grey)]
@ -31,7 +34,7 @@ namespace DCFApixels.DragonECS
public EcsPool<TComponent> pool;
public Aspect(Builder b) => pool = b.Include<TComponent>();
}
List<EcsWorld> _worlds = new List<EcsWorld>();
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
public void Inject(EcsWorld obj) => _worlds.Add(obj);
public void Run(EcsPipeline pipeline)
{

View File

@ -160,7 +160,7 @@ namespace DCFApixels.DragonECS
}
public EcsPipeline Build()
{
Add(new DeleteEmptyEntitesSystem(), EcsConsts.POST_END_LAYER);
Add(new EndFrameSystem(), EcsConsts.POST_END_LAYER);
List<IEcsProcess> result = new List<IEcsProcess>(32);
List<IEcsProcess> basicBlockList = _systems[_basicLayer];
foreach (var item in _systems)

View File

@ -2,6 +2,7 @@
using DCFApixels.DragonECS.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
@ -21,6 +22,8 @@ namespace DCFApixels.DragonECS
private int[] _delEntBuffer;
private int _delEntBufferCount;
private int _delEntBufferMinCount;
private int _usedSpace;
private List<WeakReference<EcsGroup>> _groups = new List<WeakReference<EcsGroup>>();
private Stack<EcsGroup> _groupsPool = new Stack<EcsGroup>(64);
@ -32,6 +35,7 @@ namespace DCFApixels.DragonECS
public bool IsDestroyed => _isDestroyed;
public int Count => _entitiesCount;
public int Capacity => _entitesCapacity; //_denseEntities.Length;
internal int DelBufferCount => _usedSpace - _entitiesCount; //_denseEntities.Length;
public EcsReadonlyGroup Entities => _allEntites.Readonly;
public ReadOnlySpan<IEcsPoolImplementation> AllPools => _pools;// new ReadOnlySpan<IEcsPoolImplementation>(pools, 0, _poolsCount);
#endregion
@ -59,7 +63,9 @@ namespace DCFApixels.DragonECS
ArrayUtility.Fill(_gens, DEATH_GEN_BIT);
_delEntBufferCount = 0;
_delEntBuffer = new int[_entitesCapacity >> DEL_ENT_BUFFER_SIZE_OFFSET];
//_delEntBuffer = new int[_entitesCapacity >> DEL_ENT_BUFFER_SIZE_OFFSET];
_delEntBuffer = new int[_entitesCapacity];
_delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE);
_allEntites = GetFreeGroup();
}
@ -127,15 +133,23 @@ namespace DCFApixels.DragonECS
#endregion
#region Entity
private int FreeSpace => Capacity - _usedSpace;
public int NewEmptyEntity()
{
if(FreeSpace <= 1 && DelBufferCount > _delEntBufferMinCount)
ReleaseDelEntityBuffer();
int entityID = _entityDispenser.GetFree();
_usedSpace++;
_entitiesCount++;
if (_gens.Length <= entityID)
{
Array.Resize(ref _gens, _gens.Length << 1);
Array.Resize(ref _componentCounts, _gens.Length);
Array.Resize(ref _delEntBuffer, _gens.Length);
_delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE);
ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitesCapacity);
_entitesCapacity = _gens.Length;
@ -213,12 +227,15 @@ namespace DCFApixels.DragonECS
}
public void ReleaseDelEntityBuffer()
{
if (_delEntBufferCount <= 0)
return;
ReadOnlySpan<int> buffser = new ReadOnlySpan<int>(_delEntBuffer, 0, _delEntBufferCount);
foreach (var pool in _pools)
pool.OnReleaseDelEntityBuffer(buffser);
_listeners.InvokeOnReleaseDelEntityBuffer(buffser);
for (int i = 0; i < _delEntBufferCount; i++)
_entityDispenser.Release(_delEntBuffer[i]);
_usedSpace = _entitiesCount;
_delEntBufferCount = 0;
}
public void DeleteEmptyEntites()

View File

@ -18,7 +18,8 @@ namespace DCFApixels.DragonECS
{
private const short GEN_BITS = 0x7fff;
private const short DEATH_GEN_BIT = short.MinValue;
private const int DEL_ENT_BUFFER_SIZE_OFFSET = 2;
private const int DEL_ENT_BUFFER_SIZE_OFFSET = 5;
private const int DEL_ENT_BUFFER_MIN_SIZE = 64;
private static EcsWorld[] Worlds = new EcsWorld[4];
private static IdDispenser _worldIdDispenser = new IdDispenser(0);