From 55ef119aff3d8c51a28f65d3a16baa0a95ca1f52 Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Tue, 11 Mar 2025 14:30:33 +0800 Subject: [PATCH] add optimization with IEntityStorage to EcsMaskIterator --- src/Collections/EcsSpan.cs | 14 +++++- src/EcsMask.cs | 57 +++++++++++++++++++----- src/EcsWorld.cs | 10 ++++- src/EcsWorld.static.cs | 2 +- src/Executors/EcsWhereExecutor.cs | 8 ++++ src/Executors/EcsWhereToGroupExecutor.cs | 4 ++ src/Executors/MaskQueryExecutor.cs | 4 +- src/Executors/Queries.cs | 30 ------------- 8 files changed, 83 insertions(+), 46 deletions(-) diff --git a/src/Collections/EcsSpan.cs b/src/Collections/EcsSpan.cs index 78f32f3..16aae99 100644 --- a/src/Collections/EcsSpan.cs +++ b/src/Collections/EcsSpan.cs @@ -24,7 +24,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _worldID == 0; } } - public int WorldID + public short WorldID { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _worldID; } @@ -43,6 +43,11 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new EcsLongsSpan(this); } } + public bool IsSourceEntities + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return this == EcsWorld.GetWorld(_worldID).GetCurrentEntities_Internal(); } + } #if ENABLE_IL2CPP [Il2CppSetOption(Option.ArrayBoundsChecks, true)] #endif @@ -180,7 +185,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _source.IsNull; } } - public int WorldID + public short WorldID { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _source.WorldID; } @@ -194,6 +199,11 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _source.Count; } } + public bool IsSourceEntities + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _source.IsSourceEntities; } + } #if ENABLE_IL2CPP [Il2CppSetOption(Option.ArrayBoundsChecks, true)] #endif diff --git a/src/EcsMask.cs b/src/EcsMask.cs index cbbb53a..91149c4 100644 --- a/src/EcsMask.cs +++ b/src/EcsMask.cs @@ -498,7 +498,10 @@ namespace DCFApixels.DragonECS /// slised _sortIncChunckBuffer private readonly UnsafeArray _sortExcChunckBuffer; + private readonly bool _isSingleIncPoolWithEntityStorage; + private readonly bool _isHasAnyEntityStorage; private readonly MaskType _maskType; + private enum MaskType : byte { Empty, @@ -512,11 +515,6 @@ namespace DCFApixels.DragonECS World = source; Mask = mask; - //_sortIncBuffer = UnsafeArray.FromArray(mask._incs); - //_sortExcBuffer = UnsafeArray.FromArray(mask._excs); - //_sortIncChunckBuffer = UnsafeArray.FromArray(mask._incChunckMasks); - //_sortExcChunckBuffer = UnsafeArray.FromArray(mask._excChunckMasks); - var sortBuffer = new UnsafeArray(mask._incs.Length + mask._excs.Length); var sortChunckBuffer = new UnsafeArray(mask._incChunckMasks.Length + mask._excChunckMasks.Length); @@ -530,6 +528,16 @@ namespace DCFApixels.DragonECS _sortExcChunckBuffer = sortChunckBuffer.Slice(mask._incChunckMasks.Length, mask._excChunckMasks.Length); _sortExcChunckBuffer.CopyFromArray_Unchecked(mask._excChunckMasks); + _isHasAnyEntityStorage = false; + var pools = source.AllPools; + for (int i = 0; i < _sortIncBuffer.Length; i++) + { + var pool = pools[_sortIncBuffer.ptr[i]]; + _isHasAnyEntityStorage |= pool is IEntityStorage; + if (_isHasAnyEntityStorage) { break; } + } + + _isSingleIncPoolWithEntityStorage = Mask.Excs.Length <= 0 && Mask.Incs.Length == 1; if (_sortExcBuffer.Length <= 0) { _maskType = mask.IsEmpty ? MaskType.Empty : MaskType.OnlyInc; @@ -594,9 +602,26 @@ namespace DCFApixels.DragonECS // Выражение мало IncCount < (AllEntitesCount - ExcCount) вероятно будет истинным. // ExcCount = максимальное количество ентитей с исключеющим ограничением и IncCount = минимальоне количество ентитей с включающим ограничением // Поэтому исключающее ограничение игнорируется для maxEntites. - return maxEntites; } + private unsafe bool TryGetEntityStorage(out IEntityStorage storage) + { + if (_isHasAnyEntityStorage) + { + var pools = World.AllPools; + for (int i = 0; i < _sortIncBuffer.Length; i++) + { + var pool = pools[_sortIncBuffer.ptr[i]]; + storage = pool as IEntityStorage; + if (storage != null) + { + return true; + } + } + } + storage = null; + return false; + } #endregion #region IterateTo @@ -694,7 +719,6 @@ namespace DCFApixels.DragonECS #endregion #region Enumerator - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { if (_iterator.Mask.IsBroken) @@ -706,7 +730,14 @@ namespace DCFApixels.DragonECS { return new Enumerator(_span.Slice(0, 0), _iterator); } - return new Enumerator(_span, _iterator); + if (_iterator.TryGetEntityStorage(out IEntityStorage storage)) + { + return new Enumerator(storage.ToSpan(), _iterator); + } + else + { + return new Enumerator(_span, _iterator); + } } #if ENABLE_IL2CPP @@ -827,7 +858,6 @@ namespace DCFApixels.DragonECS #endregion #region Enumerator - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { if (_iterator.Mask.IsBroken) @@ -839,7 +869,14 @@ namespace DCFApixels.DragonECS { return new Enumerator(_span.Slice(0, 0), _iterator); } - return new Enumerator(_span, _iterator); + if (_iterator.TryGetEntityStorage(out IEntityStorage storage)) + { + return new Enumerator(storage.ToSpan(), _iterator); + } + else + { + return new Enumerator(_span, _iterator); + } } #if ENABLE_IL2CPP diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 3c36bf6..6639c98 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -130,7 +130,7 @@ namespace DCFApixels.DragonECS get { ReleaseDelEntityBufferAll(); - return _entityDispenser.UsedToEcsSpan(ID); + return GetCurrentEntities_Internal(); } } public int PoolsCount @@ -1167,6 +1167,14 @@ namespace DCFApixels.DragonECS } } #endregion + + #region Internal + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal EcsSpan GetCurrentEntities_Internal() + { + return _entityDispenser.UsedToEcsSpan(ID); + } + #endregion } #region Callbacks Interface diff --git a/src/EcsWorld.static.cs b/src/EcsWorld.static.cs index 2798fd8..1311bd8 100644 --- a/src/EcsWorld.static.cs +++ b/src/EcsWorld.static.cs @@ -73,7 +73,7 @@ namespace DCFApixels.DragonECS var world = _worlds[i]; if (world == null) { continue; } - if(world.IsDestroyed == false) + if (world.IsDestroyed == false) { world.Destroy(); } diff --git a/src/Executors/EcsWhereExecutor.cs b/src/Executors/EcsWhereExecutor.cs index bc9bc50..9cb4df3 100644 --- a/src/Executors/EcsWhereExecutor.cs +++ b/src/Executors/EcsWhereExecutor.cs @@ -91,6 +91,10 @@ namespace DCFApixels.DragonECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public EcsSpan ExecuteFor(EcsSpan span) { + if (span.IsSourceEntities) + { + return Execute(); + } ExecuteFor_Iternal(span); return new EcsSpan(World.ID, _filteredEntities, _filteredEntitiesCount); } @@ -105,6 +109,10 @@ namespace DCFApixels.DragonECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public EcsSpan ExecuteFor(EcsSpan span, Comparison comparison) { + if (span.IsSourceEntities) + { + return Execute(comparison); + } ExecuteFor_Iternal(span); ArraySortHalperX.Sort(_filteredEntities, comparison, _filteredEntitiesCount); return new EcsSpan(World.ID, _filteredEntities, _filteredEntitiesCount); diff --git a/src/Executors/EcsWhereToGroupExecutor.cs b/src/Executors/EcsWhereToGroupExecutor.cs index 8511206..8f9d046 100644 --- a/src/Executors/EcsWhereToGroupExecutor.cs +++ b/src/Executors/EcsWhereToGroupExecutor.cs @@ -90,6 +90,10 @@ namespace DCFApixels.DragonECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public EcsReadonlyGroup ExecuteFor(EcsSpan span) { + if (span.IsSourceEntities) + { + return Execute(); + } ExecuteFor_Iternal(span); return _filteredGroup; } diff --git a/src/Executors/MaskQueryExecutor.cs b/src/Executors/MaskQueryExecutor.cs index d6f70f2..96e786a 100644 --- a/src/Executors/MaskQueryExecutor.cs +++ b/src/Executors/MaskQueryExecutor.cs @@ -120,7 +120,7 @@ namespace DCFApixels.DragonECS.Core _world = mask.World; _maskInc = mask._incs; _maskExc = mask._excs; - _versions = UnmanagedArrayUtility.New(1 + mask._incs.Length + mask._excs.Length); + _versions = UnmanagedArrayUtility.NewAndInit(1 + mask._incs.Length + mask._excs.Length); } public bool Check() { @@ -176,7 +176,7 @@ namespace DCFApixels.DragonECS.Core long* ptr = _versions; var slots = _world._poolSlots; - bool result = true; + bool result = _maskInc.Length > 0 || _maskExc.Length > 0; foreach (var slotIndex in _maskInc) { ptr++; diff --git a/src/Executors/Queries.cs b/src/Executors/Queries.cs index 171386f..96d0eed 100644 --- a/src/Executors/Queries.cs +++ b/src/Executors/Queries.cs @@ -16,11 +16,6 @@ namespace DCFApixels.DragonECS where TAspect : new() where TCollection : IEntityStorage { - if (ReferenceEquals(entities, entities.World)) - { - entities.World.GetQueryCache(out EcsWhereExecutor executor, out aspect); - return executor.Execute(); - } return entities.ToSpan().Where(out aspect); } public static EcsSpan Where(this EcsReadonlyGroup group, out TAspect aspect) @@ -38,11 +33,6 @@ namespace DCFApixels.DragonECS public static EcsSpan Where(this TCollection entities, IComponentMask mask) where TCollection : IEntityStorage { - if (ReferenceEquals(entities, entities.World)) - { - var executor = entities.World.GetExecutorForMask(mask); - return executor.Execute(); - } return entities.ToSpan().Where(mask); } public static EcsSpan Where(this EcsReadonlyGroup group, IComponentMask mask) @@ -61,11 +51,6 @@ namespace DCFApixels.DragonECS where TAspect : new() where TCollection : IEntityStorage { - if (ReferenceEquals(entities, entities.World)) - { - entities.World.GetQueryCache(out EcsWhereExecutor executor, out aspect); - return executor.Execute(comparison); - } return entities.ToSpan().Where(out aspect, comparison); } public static EcsSpan Where(this EcsReadonlyGroup group, out TAspect aspect, Comparison comparison) @@ -83,11 +68,6 @@ namespace DCFApixels.DragonECS public static EcsSpan Where(this TCollection entities, IComponentMask mask, Comparison comparison) where TCollection : IEntityStorage { - if (ReferenceEquals(entities, entities.World)) - { - EcsWhereExecutor executor = entities.World.GetExecutorForMask(mask); - return executor.Execute(comparison); - } return entities.ToSpan().Where(mask, comparison); } public static EcsSpan Where(this EcsReadonlyGroup group, IComponentMask mask, Comparison comparison) @@ -106,11 +86,6 @@ namespace DCFApixels.DragonECS where TAspect : new() where TCollection : IEntityStorage { - if (ReferenceEquals(entities, entities.World)) - { - entities.World.GetQueryCache(out EcsWhereToGroupExecutor executor, out aspect); - return executor.Execute(); - } return entities.ToSpan().WhereToGroup(out aspect); } public static EcsReadonlyGroup WhereToGroup(this EcsReadonlyGroup group, out TAspect aspect) @@ -128,11 +103,6 @@ namespace DCFApixels.DragonECS public static EcsReadonlyGroup WhereToGroup(this TCollection entities, IComponentMask mask) where TCollection : IEntityStorage { - if (ReferenceEquals(entities, entities.World)) - { - EcsWhereToGroupExecutor executor = entities.World.GetExecutorForMask(mask); - return executor.Execute(); - } return entities.ToSpan().WhereToGroup(mask); } public static EcsReadonlyGroup WhereToGroup(this EcsReadonlyGroup group, IComponentMask mask)