From 58f604e811af4cb56fa010daedee3e0997eac8e1 Mon Sep 17 00:00:00 2001 From: Ullrich Praetz Date: Tue, 28 May 2024 15:29:31 +0200 Subject: [PATCH] Engine - ECS: simplify / optimize Archetype.CreateEntities() --- Engine/src/ECS/Archetype/Archetype.cs | 23 +++++-------------- Engine/src/ECS/Archetype/Entities.cs | 6 ++--- Engine/src/ECS/Entity/Store/Entities.cs | 11 +++++---- .../src/Tests/ECS/Entity/Test_StructHeap.cs | 19 +++++++-------- 4 files changed, 25 insertions(+), 34 deletions(-) diff --git a/Engine/src/ECS/Archetype/Archetype.cs b/Engine/src/ECS/Archetype/Archetype.cs index 0cd188913..c7dc9d638 100644 --- a/Engine/src/ECS/Archetype/Archetype.cs +++ b/Engine/src/ECS/Archetype/Archetype.cs @@ -121,30 +121,19 @@ public Entity CreateEntity(int id) return entity; } - public EntityList CreateEntities(int count, EntityList list = null) + public Entities CreateEntities(int count) { - if (list == null) { - list = new EntityList(entityStore); - } else { - list.Clear(); - list.SetStore(entityStore); - } - list.Capacity = count; - var localStore = entityStore; - var ids = list.ids; - localStore.NewIds(ids, count); - list.count = count; - var maxId = list.ids[count - 1]; + var localStore = entityStore; int compIndexStart = entityCount; - localStore.CreateEntityNodes(this, ids, count, maxId); + localStore.CreateEntityNodes(this, count); foreach (var heap in structHeaps) { heap.SetComponentsDefault(compIndexStart, count); } - // Send event. See: SEND_EVENT notes - localStore.CreateEntityEvents(ids, count); - return list; + var entities = new Entities(entityIds, localStore, compIndexStart, count); + localStore.CreateEntityEvents(entities); + return entities; } /// diff --git a/Engine/src/ECS/Archetype/Entities.cs b/Engine/src/ECS/Archetype/Entities.cs index 8aaad5082..e8c7bc728 100644 --- a/Engine/src/ECS/Archetype/Entities.cs +++ b/Engine/src/ECS/Archetype/Entities.cs @@ -17,7 +17,7 @@ namespace Friflo.Engine.ECS; internal readonly int[] ids; // 8 internal readonly EntityStore store; // 8 internal readonly int start; // 4 - public readonly int count; // 4 + internal readonly int count; // 4 #endregion #region general @@ -49,13 +49,13 @@ public struct EntityEnumerator : IEnumerator private readonly int[] ids; // 8 private readonly EntityStore store; // 8 private readonly int start; // 4 - private readonly int last; // 8 + private readonly int last; // 4 private int index; // 4 internal EntityEnumerator(in Entities entities) { ids = entities.ids; store = entities.store; - start = entities.start; + start = entities.start - 1; last = start + entities.count; index = start; } diff --git a/Engine/src/ECS/Entity/Store/Entities.cs b/Engine/src/ECS/Entity/Store/Entities.cs index 4bf43072c..4f2ed77c0 100644 --- a/Engine/src/ECS/Entity/Store/Entities.cs +++ b/Engine/src/ECS/Entity/Store/Entities.cs @@ -172,8 +172,9 @@ private int CreateEntityNode(Archetype archetype, int id) return node.compIndex; } - internal void CreateEntityNodes(Archetype archetype, int[] ids, int count, int maxId) + internal void CreateEntityNodes(Archetype archetype, int count) { + int maxId = intern.sequenceId + count; EnsureNodesLength(maxId + 1); archetype.EnsureCapacity(count); int compIndexStart = archetype.entityCount; @@ -181,7 +182,7 @@ internal void CreateEntityNodes(Archetype archetype, int[] ids, int count, int m var localNodes = nodes; for (int n = 0; n < count; n++) { - var id = ids[n]; + var id = NewId(); AssertIdInNodes(id); ref var node = ref localNodes[id]; if ((node.flags & Created) != 0) { @@ -218,14 +219,14 @@ private QueryEntities GetEntities() { return query.Entities; } - internal void CreateEntityEvents(int[] ids, int count) + internal void CreateEntityEvents(Entities entities) { var create = intern.entityCreate; if (create == null) { return; } - for (int n = 0; n < count; n++) { - create(new EntityCreate(new Entity(this, ids[n]))); + foreach (var entity in entities) { + create(new EntityCreate(entity)); } } diff --git a/Engine/src/Tests/ECS/Entity/Test_StructHeap.cs b/Engine/src/Tests/ECS/Entity/Test_StructHeap.cs index 4be6a6e69..b28b36007 100644 --- a/Engine/src/Tests/ECS/Entity/Test_StructHeap.cs +++ b/Engine/src/Tests/ECS/Entity/Test_StructHeap.cs @@ -109,18 +109,19 @@ public static void Test_StructHeap_CreateEntities() Mem.AreEqual(evId++, create.Entity.Id); }; for (int n = 0; n < repeat; n++) { - var start = Mem.GetAllocatedBytes(); - type.CreateEntities(count, list); + var start = Mem.GetAllocatedBytes(); + var entities = type.CreateEntities(count); Mem.AssertNoAlloc(start); - for (int i = 0; i < count; i++) { - var entity = list[i]; + foreach (var entity in entities) { Assert.AreSame(type, entity.Archetype); Assert.AreEqual(seqId++, entity.Id); } } - list = type.CreateEntities(count); // list = null - for (int i = 0; i < count; i++) { - Assert.AreEqual(seqId++, list[i].Id); + { + var entities = type.CreateEntities(count); // list = null + foreach (var entity in entities) { + Assert.AreEqual(seqId++, entity.Id); + } } var entityCount = (1 + repeat) * count; Assert.AreEqual(entityCount, store.Count); @@ -189,14 +190,14 @@ public static void Test_StructHeap_CreateEntities_Perf() /* #PC: Archetype.CreateEntities() Entity count: 100000, repeat: 1000, duration: 1,479 ms */ - var list = new EntityList(); var sw = new Stopwatch(); sw.Start(); for (int i = 0; i < repeat; i++) { var store = new EntityStore(); var type = store.GetArchetype(ComponentTypes.Get()); - type.CreateEntities(count, list); + var entities = type.CreateEntities(count); + Mem.AreEqual(count, entities.Count); } var duration = (double)sw.ElapsedMilliseconds / repeat; Console.WriteLine($"Archetype.CreateEntities() Entity count: {count}, repeat: {repeat}, duration: {duration} ms");