From 93ed5c8dd288effc0a0f9fb0d67bf2814196f5e6 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 13 Dec 2022 15:14:27 -0800 Subject: [PATCH] more garbage optimization --- src/EntityComponentReader.cs | 4 +-- src/Relation.cs | 31 ----------------------- src/RelationDepot.cs | 16 ++++++------ src/RelationStorage.cs | 49 ++++++++++++++++++------------------ src/System.cs | 4 +-- src/TemplateStorage.cs | 4 +-- 6 files changed, 38 insertions(+), 70 deletions(-) delete mode 100644 src/Relation.cs diff --git a/src/EntityComponentReader.cs b/src/EntityComponentReader.cs index efdf50d..e55f6dd 100644 --- a/src/EntityComponentReader.cs +++ b/src/EntityComponentReader.cs @@ -52,7 +52,7 @@ namespace MoonTools.ECS return ComponentDepot.GetSingletonEntity(); } - protected IEnumerable<(Entity, Entity, TRelationKind)> Relations() where TRelationKind : unmanaged + protected ReverseSpanEnumerator<(Entity, Entity)> Relations() where TRelationKind : unmanaged { return RelationDepot.Relations(); } @@ -64,7 +64,7 @@ namespace MoonTools.ECS protected TRelationKind GetRelationData(in Entity a, in Entity b) where TRelationKind : unmanaged { - return RelationDepot.Get(new Relation(a.ID, b.ID)); + return RelationDepot.Get(a, b); } // relations go A->B, so given A, will give all entities in outgoing relations of this kind. diff --git a/src/Relation.cs b/src/Relation.cs deleted file mode 100644 index 6dccd3a..0000000 --- a/src/Relation.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; - -namespace MoonTools.ECS -{ - internal struct Relation : IEquatable - { - public Entity A { get; } - public Entity B { get; } - - internal Relation(Entity entityA, Entity entityB) - { - A = entityA; - B = entityB; - } - - public override bool Equals(object? obj) - { - return obj is Relation relation && Equals(relation); - } - - public bool Equals(Relation other) - { - return A.ID == other.A.ID && B.ID == other.B.ID; - } - - public override int GetHashCode() - { - return HashCode.Combine(A.ID, B.ID); - } - } -} diff --git a/src/RelationDepot.cs b/src/RelationDepot.cs index abea455..06bb2fe 100644 --- a/src/RelationDepot.cs +++ b/src/RelationDepot.cs @@ -36,19 +36,19 @@ namespace MoonTools.ECS return (RelationStorage) storages[storageIndex]; } - public void Set(Relation relation, TRelationKind relationData) where TRelationKind : unmanaged + public void Set(in Entity entityA, in Entity entityB, TRelationKind relationData) where TRelationKind : unmanaged { - Lookup().Set(relation, relationData); + Lookup().Set(entityA, entityB, relationData); } - public TRelationKind Get(Relation relation) where TRelationKind : unmanaged + public TRelationKind Get(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged { - return Lookup().Get(relation); + return Lookup().Get(entityA, entityB); } - public (bool, bool) Remove(Relation relation) where TRelationKind : unmanaged + public (bool, bool) Remove(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged { - return Lookup().Remove(relation); + return Lookup().Remove(entityA, entityB); } public void UnrelateAll(int entityID) where TRelationKind : unmanaged @@ -56,14 +56,14 @@ namespace MoonTools.ECS Lookup().UnrelateAll(entityID); } - public IEnumerable<(Entity, Entity, TRelationKind)> Relations() where TRelationKind : unmanaged + public ReverseSpanEnumerator<(Entity, Entity)> Relations() where TRelationKind : unmanaged { return Lookup().All(); } public bool Related(int idA, int idB) where TRelationKind : unmanaged { - return Lookup().Has(new Relation(idA, idB)); + return Lookup().Has((idA, idB)); } public ReverseSpanEnumerator OutRelations(int entityID) where TRelationKind : unmanaged diff --git a/src/RelationStorage.cs b/src/RelationStorage.cs index 7c522c5..a069768 100644 --- a/src/RelationStorage.cs +++ b/src/RelationStorage.cs @@ -19,32 +19,30 @@ namespace MoonTools.ECS internal class RelationStorage : RelationStorage where TRelation : unmanaged { private int count = 0; - private Dictionary indices = new Dictionary(16); - private Relation[] relations = new Relation[16]; + private Dictionary<(Entity, Entity), int> indices = new Dictionary<(Entity, Entity), int>(16); + private (Entity, Entity)[] relations = new (Entity, Entity)[16]; private TRelation[] relationDatas = new TRelation[16]; private Dictionary> outRelations = new Dictionary>(16); private Dictionary> inRelations = new Dictionary>(16); private Stack> listPool = new Stack>(); - public IEnumerable<(Entity, Entity, TRelation)> All() + public ReverseSpanEnumerator<(Entity, Entity)> All() { - for (var i = 0; i < count; i += 1) - { - var relation = relations[i]; - yield return (relation.A, relation.B, relationDatas[i]); - } + return new ReverseSpanEnumerator<(Entity, Entity)>(new Span<(Entity, Entity)>(relations, 0, count)); } - public void Set(Relation relation, TRelation relationData) + public void Set(in Entity entityA, in Entity entityB, TRelation relationData) { + var relation = (entityA, entityB); + if (indices.TryGetValue(relation, out var index)) { relationDatas[index] = relationData; return; } - var idA = relation.A.ID; - var idB = relation.B.ID; + var idA = entityA.ID; + var idB = entityB.ID; if (!outRelations.ContainsKey(idA)) { @@ -70,12 +68,12 @@ namespace MoonTools.ECS count += 1; } - public TRelation Get(Relation relation) + public TRelation Get(in Entity entityA, in Entity entityB) { - return relationDatas[indices[relation]]; + return relationDatas[indices[(entityA, entityB)]]; } - public bool Has(Relation relation) + public bool Has((Entity, Entity) relation) { return indices.ContainsKey(relation); } @@ -147,24 +145,25 @@ namespace MoonTools.ECS return inRelations.TryGetValue(entityID, out var entityInRelations) ? entityInRelations.Count : 0; } - public (bool, bool) Remove(Relation relation) + public (bool, bool) Remove(in Entity entityA, in Entity entityB) { var aEmpty = false; var bEmpty = false; + var relation = (entityA, entityB); - if (outRelations.TryGetValue(relation.A.ID, out var entityOutRelations)) + if (outRelations.TryGetValue(entityA.ID, out var entityOutRelations)) { - entityOutRelations.Remove(relation.B.ID); - if (outRelations[relation.A.ID].Count == 0) + entityOutRelations.Remove(entityB.ID); + if (outRelations[entityA.ID].Count == 0) { aEmpty = true; } } - if (inRelations.TryGetValue(relation.B.ID, out var entityInRelations)) + if (inRelations.TryGetValue(entityB.ID, out var entityInRelations)) { - entityInRelations.Remove(relation.A.ID); - if (inRelations[relation.B.ID].Count == 0) + entityInRelations.Remove(entityA.ID); + if (inRelations[entityB.ID].Count == 0) { bEmpty = true; } @@ -210,12 +209,12 @@ namespace MoonTools.ECS public override unsafe void Set(int entityA, int entityB, void* relationData) { - Set(new Relation(entityA, entityB), *((TRelation*) relationData)); + Set(entityA, entityB, *((TRelation*) relationData)); } public override int GetStorageIndex(int entityA, int entityB) { - return indices[new Relation(entityA, entityB)]; + return indices[(entityA, entityB)]; } public override unsafe void* Get(int relationStorageIndex) @@ -232,7 +231,7 @@ namespace MoonTools.ECS { foreach (var entityB in entityOutRelations) { - Remove(new Relation(entityID, entityB)); + Remove(entityID, entityB); } ReturnHashSetToPool(entityOutRelations); @@ -243,7 +242,7 @@ namespace MoonTools.ECS { foreach (var entityA in entityInRelations) { - Remove(new Relation(entityA, entityID)); + Remove(entityA, entityID); } ReturnHashSetToPool(entityInRelations); diff --git a/src/System.cs b/src/System.cs index 35c44a6..37dd234 100644 --- a/src/System.cs +++ b/src/System.cs @@ -70,7 +70,7 @@ namespace MoonTools.ECS protected void Relate(in Entity entityA, in Entity entityB, TRelationKind relationData) where TRelationKind : unmanaged { - RelationDepot.Set(new Relation(entityA, entityB), relationData); + RelationDepot.Set(entityA, entityB, relationData); var relationTypeIndex = RelationTypeIndices.GetIndex(); EntityStorage.AddRelationKind(entityA.ID, relationTypeIndex); EntityStorage.AddRelationKind(entityB.ID, relationTypeIndex); @@ -78,7 +78,7 @@ namespace MoonTools.ECS protected void Unrelate(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged { - var (aEmpty, bEmpty) = RelationDepot.Remove(new Relation(entityA, entityB)); + var (aEmpty, bEmpty) = RelationDepot.Remove(entityA, entityB); if (aEmpty) { diff --git a/src/TemplateStorage.cs b/src/TemplateStorage.cs index c45f32f..fb9dfa0 100644 --- a/src/TemplateStorage.cs +++ b/src/TemplateStorage.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace MoonTools.ECS { @@ -19,7 +19,7 @@ namespace MoonTools.ECS return TemplateToComponentTypeIndices[templateID].Add(componentTypeIndex); } - public IEnumerable ComponentTypeIndices(int templateID) + public HashSet ComponentTypeIndices(int templateID) { return TemplateToComponentTypeIndices[templateID]; }