Skip to content

Commit c3be704

Browse files
committed
Try holding less archetype references for GC speed
1 parent 8035dd5 commit c3be704

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

src/ArchetypeContainer.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
1+
using System.Threading;
12
using System.Linq;
23
using System.Collections.Generic;
34
using System;
5+
using System.Collections.Concurrent;
46

57
namespace SimpleECS
68
{
79
class ArchetypeContainer
810
{
11+
static ConcurrentDictionary<int, WeakReference<ArchetypeContainer>> archetypesById = new ConcurrentDictionary<int, WeakReference<ArchetypeContainer>>();
12+
13+
public static ArchetypeContainer? GetById(int id)
14+
{
15+
if (archetypesById.TryGetValue(id, out var weakReference))
16+
{
17+
if (weakReference.TryGetTarget(out var target))
18+
return target;
19+
else
20+
archetypesById.Remove(id, out _);
21+
}
22+
return null;
23+
}
24+
public int ID { get; }
25+
static int highestArchetypeId;
26+
927
internal Dictionary<Type, Array> arrays = new Dictionary<Type, Array>();
1028
internal Dictionary<(int, Type), ArrayElementRef> additions = new Dictionary<(int, Type), ArrayElementRef>();
1129
internal HashSet<(int, Type)> removals = new HashSet<(int, Type)>();
@@ -22,6 +40,10 @@ class ArchetypeContainer
2240

2341
internal ArchetypeContainer(Scene scene)
2442
{
43+
ID = Interlocked.Increment(ref highestArchetypeId);
44+
if(!archetypesById.TryAdd(ID, new WeakReference<ArchetypeContainer>(this)))
45+
throw new Exception();
46+
2547
this.scene = scene;
2648
entityIds = new int[capacity];
2749
}

src/EntityRegistry.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public EntityLocation(ArchetypeContainer archetypeContainer, int index)
1919
}
2020

2121
private const int InitialCapacity = 512;
22-
EntityLocation[] Locations = new EntityLocation[InitialCapacity];
22+
int[] entityArchetypes = new int[InitialCapacity];
23+
int[] entityIndices = new int[InitialCapacity];
2324
int[] Versions = new int[InitialCapacity];
2425
HashSet<int> freeIDs = new HashSet<int>();
2526
int nextId = 0;
@@ -30,8 +31,13 @@ public EntityLocation(ArchetypeContainer archetypeContainer, int index)
3031

3132
public Entity RegisterEntity(ArchetypeContainer container, int index)
3233
{
33-
if (nextId == Locations.Length)
34-
Array.Resize(ref Locations, Locations.Length * 2);
34+
if (nextId == entityArchetypes.Length)
35+
{
36+
int newSize = entityArchetypes.Length * 2;
37+
Array.Resize(ref entityArchetypes, newSize);
38+
Array.Resize(ref entityIndices, newSize);
39+
Array.Resize(ref Versions, newSize);
40+
}
3541
int id;
3642
if (freeIDs.Count > 0)
3743
{
@@ -45,21 +51,24 @@ public Entity RegisterEntity(ArchetypeContainer container, int index)
4551
id = nextId;
4652
nextId++;
4753
}
48-
Locations[id] = new EntityLocation(container, index);
54+
entityArchetypes[id] = container.ID;
55+
entityIndices[id] = index;
4956
return new Entity(id, Versions[id]);
5057
}
5158
public void UnregisterEntity(Entity entity, out EntityLocation lastLocation)
5259
{
5360
if (entity.Version != Versions[entity.Id])
5461
throw new Exception("The entity was already deleted.");
55-
lastLocation = Locations[entity.Id];
56-
Locations[entity.Id] = default;
62+
lastLocation = GetLocation(entity);
63+
entityArchetypes[entity.Id] = 0;
64+
entityIndices[entity.Id] = 0;
5765
Versions[entity.Id]++;
5866
freeIDs.Add(entity.Id);
5967
}
6068
public void MoveEntity(int entity, ArchetypeContainer newContainer, int newIndex)
6169
{
62-
Locations[entity] = new EntityLocation(newContainer, newIndex);
70+
entityArchetypes[entity] = newContainer.ID;
71+
entityIndices[entity] = newIndex;
6372
}
6473
public bool TryGetLocation(Entity entity, out EntityLocation location)
6574
{
@@ -70,11 +79,16 @@ public bool TryGetLocation(Entity entity, out EntityLocation location)
7079
}
7180
else
7281
{
73-
location = Locations[entity.Id];
82+
location = GetLocation(entity);
7483
return true;
7584
}
7685
}
7786

87+
private EntityLocation GetLocation(Entity entity)
88+
=> new EntityLocation(
89+
ArchetypeContainer.GetById(entityArchetypes[entity.Id])!,
90+
entityIndices[entity.Id]);
91+
7892
public IEnumerator<Entity> GetEnumerator() => new EntityEnumerator(this);
7993
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
8094
struct EntityEnumerator : IEnumerator<Entity>

0 commit comments

Comments
 (0)