more garbage optimization

filter_relations
cosmonaut 2022-12-13 15:14:27 -08:00
parent 2f46af30fb
commit 93ed5c8dd2
6 changed files with 38 additions and 70 deletions

View File

@ -52,7 +52,7 @@ namespace MoonTools.ECS
return ComponentDepot.GetSingletonEntity<TComponent>(); return ComponentDepot.GetSingletonEntity<TComponent>();
} }
protected IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : unmanaged protected ReverseSpanEnumerator<(Entity, Entity)> Relations<TRelationKind>() where TRelationKind : unmanaged
{ {
return RelationDepot.Relations<TRelationKind>(); return RelationDepot.Relations<TRelationKind>();
} }
@ -64,7 +64,7 @@ namespace MoonTools.ECS
protected TRelationKind GetRelationData<TRelationKind>(in Entity a, in Entity b) where TRelationKind : unmanaged protected TRelationKind GetRelationData<TRelationKind>(in Entity a, in Entity b) where TRelationKind : unmanaged
{ {
return RelationDepot.Get<TRelationKind>(new Relation(a.ID, b.ID)); return RelationDepot.Get<TRelationKind>(a, b);
} }
// relations go A->B, so given A, will give all entities in outgoing relations of this kind. // relations go A->B, so given A, will give all entities in outgoing relations of this kind.

View File

@ -1,31 +0,0 @@
using System;
namespace MoonTools.ECS
{
internal struct Relation : IEquatable<Relation>
{
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);
}
}
}

View File

@ -36,19 +36,19 @@ namespace MoonTools.ECS
return (RelationStorage<TRelationKind>) storages[storageIndex]; return (RelationStorage<TRelationKind>) storages[storageIndex];
} }
public void Set<TRelationKind>(Relation relation, TRelationKind relationData) where TRelationKind : unmanaged public void Set<TRelationKind>(in Entity entityA, in Entity entityB, TRelationKind relationData) where TRelationKind : unmanaged
{ {
Lookup<TRelationKind>().Set(relation, relationData); Lookup<TRelationKind>().Set(entityA, entityB, relationData);
} }
public TRelationKind Get<TRelationKind>(Relation relation) where TRelationKind : unmanaged public TRelationKind Get<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged
{ {
return Lookup<TRelationKind>().Get(relation); return Lookup<TRelationKind>().Get(entityA, entityB);
} }
public (bool, bool) Remove<TRelationKind>(Relation relation) where TRelationKind : unmanaged public (bool, bool) Remove<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged
{ {
return Lookup<TRelationKind>().Remove(relation); return Lookup<TRelationKind>().Remove(entityA, entityB);
} }
public void UnrelateAll<TRelationKind>(int entityID) where TRelationKind : unmanaged public void UnrelateAll<TRelationKind>(int entityID) where TRelationKind : unmanaged
@ -56,14 +56,14 @@ namespace MoonTools.ECS
Lookup<TRelationKind>().UnrelateAll(entityID); Lookup<TRelationKind>().UnrelateAll(entityID);
} }
public IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : unmanaged public ReverseSpanEnumerator<(Entity, Entity)> Relations<TRelationKind>() where TRelationKind : unmanaged
{ {
return Lookup<TRelationKind>().All(); return Lookup<TRelationKind>().All();
} }
public bool Related<TRelationKind>(int idA, int idB) where TRelationKind : unmanaged public bool Related<TRelationKind>(int idA, int idB) where TRelationKind : unmanaged
{ {
return Lookup<TRelationKind>().Has(new Relation(idA, idB)); return Lookup<TRelationKind>().Has((idA, idB));
} }
public ReverseSpanEnumerator<Entity> OutRelations<TRelationKind>(int entityID) where TRelationKind : unmanaged public ReverseSpanEnumerator<Entity> OutRelations<TRelationKind>(int entityID) where TRelationKind : unmanaged

View File

@ -19,32 +19,30 @@ namespace MoonTools.ECS
internal class RelationStorage<TRelation> : RelationStorage where TRelation : unmanaged internal class RelationStorage<TRelation> : RelationStorage where TRelation : unmanaged
{ {
private int count = 0; private int count = 0;
private Dictionary<Relation, int> indices = new Dictionary<Relation, int>(16); private Dictionary<(Entity, Entity), int> indices = new Dictionary<(Entity, Entity), int>(16);
private Relation[] relations = new Relation[16]; private (Entity, Entity)[] relations = new (Entity, Entity)[16];
private TRelation[] relationDatas = new TRelation[16]; private TRelation[] relationDatas = new TRelation[16];
private Dictionary<int, IndexableSet<Entity>> outRelations = new Dictionary<int, IndexableSet<Entity>>(16); private Dictionary<int, IndexableSet<Entity>> outRelations = new Dictionary<int, IndexableSet<Entity>>(16);
private Dictionary<int, IndexableSet<Entity>> inRelations = new Dictionary<int, IndexableSet<Entity>>(16); private Dictionary<int, IndexableSet<Entity>> inRelations = new Dictionary<int, IndexableSet<Entity>>(16);
private Stack<IndexableSet<Entity>> listPool = new Stack<IndexableSet<Entity>>(); private Stack<IndexableSet<Entity>> listPool = new Stack<IndexableSet<Entity>>();
public IEnumerable<(Entity, Entity, TRelation)> All() public ReverseSpanEnumerator<(Entity, Entity)> All()
{ {
for (var i = 0; i < count; i += 1) return new ReverseSpanEnumerator<(Entity, Entity)>(new Span<(Entity, Entity)>(relations, 0, count));
{
var relation = relations[i];
yield return (relation.A, relation.B, relationDatas[i]);
}
} }
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)) if (indices.TryGetValue(relation, out var index))
{ {
relationDatas[index] = relationData; relationDatas[index] = relationData;
return; return;
} }
var idA = relation.A.ID; var idA = entityA.ID;
var idB = relation.B.ID; var idB = entityB.ID;
if (!outRelations.ContainsKey(idA)) if (!outRelations.ContainsKey(idA))
{ {
@ -70,12 +68,12 @@ namespace MoonTools.ECS
count += 1; 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); return indices.ContainsKey(relation);
} }
@ -147,24 +145,25 @@ namespace MoonTools.ECS
return inRelations.TryGetValue(entityID, out var entityInRelations) ? entityInRelations.Count : 0; 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 aEmpty = false;
var bEmpty = 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); entityOutRelations.Remove(entityB.ID);
if (outRelations[relation.A.ID].Count == 0) if (outRelations[entityA.ID].Count == 0)
{ {
aEmpty = true; aEmpty = true;
} }
} }
if (inRelations.TryGetValue(relation.B.ID, out var entityInRelations)) if (inRelations.TryGetValue(entityB.ID, out var entityInRelations))
{ {
entityInRelations.Remove(relation.A.ID); entityInRelations.Remove(entityA.ID);
if (inRelations[relation.B.ID].Count == 0) if (inRelations[entityB.ID].Count == 0)
{ {
bEmpty = true; bEmpty = true;
} }
@ -210,12 +209,12 @@ namespace MoonTools.ECS
public override unsafe void Set(int entityA, int entityB, void* relationData) 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) 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) public override unsafe void* Get(int relationStorageIndex)
@ -232,7 +231,7 @@ namespace MoonTools.ECS
{ {
foreach (var entityB in entityOutRelations) foreach (var entityB in entityOutRelations)
{ {
Remove(new Relation(entityID, entityB)); Remove(entityID, entityB);
} }
ReturnHashSetToPool(entityOutRelations); ReturnHashSetToPool(entityOutRelations);
@ -243,7 +242,7 @@ namespace MoonTools.ECS
{ {
foreach (var entityA in entityInRelations) foreach (var entityA in entityInRelations)
{ {
Remove(new Relation(entityA, entityID)); Remove(entityA, entityID);
} }
ReturnHashSetToPool(entityInRelations); ReturnHashSetToPool(entityInRelations);

View File

@ -70,7 +70,7 @@ namespace MoonTools.ECS
protected void Relate<TRelationKind>(in Entity entityA, in Entity entityB, TRelationKind relationData) where TRelationKind : unmanaged protected void Relate<TRelationKind>(in Entity entityA, in Entity entityB, TRelationKind relationData) where TRelationKind : unmanaged
{ {
RelationDepot.Set<TRelationKind>(new Relation(entityA, entityB), relationData); RelationDepot.Set(entityA, entityB, relationData);
var relationTypeIndex = RelationTypeIndices.GetIndex<TRelationKind>(); var relationTypeIndex = RelationTypeIndices.GetIndex<TRelationKind>();
EntityStorage.AddRelationKind(entityA.ID, relationTypeIndex); EntityStorage.AddRelationKind(entityA.ID, relationTypeIndex);
EntityStorage.AddRelationKind(entityB.ID, relationTypeIndex); EntityStorage.AddRelationKind(entityB.ID, relationTypeIndex);
@ -78,7 +78,7 @@ namespace MoonTools.ECS
protected void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged protected void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged
{ {
var (aEmpty, bEmpty) = RelationDepot.Remove<TRelationKind>(new Relation(entityA, entityB)); var (aEmpty, bEmpty) = RelationDepot.Remove<TRelationKind>(entityA, entityB);
if (aEmpty) if (aEmpty)
{ {

View File

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace MoonTools.ECS namespace MoonTools.ECS
{ {
@ -19,7 +19,7 @@ namespace MoonTools.ECS
return TemplateToComponentTypeIndices[templateID].Add(componentTypeIndex); return TemplateToComponentTypeIndices[templateID].Add(componentTypeIndex);
} }
public IEnumerable<int> ComponentTypeIndices(int templateID) public HashSet<int> ComponentTypeIndices(int templateID)
{ {
return TemplateToComponentTypeIndices[templateID]; return TemplateToComponentTypeIndices[templateID];
} }