Skip to content

Commit de8316e

Browse files
Fixes
1 parent 3c91cef commit de8316e

File tree

3 files changed

+84
-15
lines changed

3 files changed

+84
-15
lines changed

src/Arch.Benchmarks/TryGetBenchmark.cs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ namespace Arch.Benchmarks;
55

66
[HtmlExporter]
77
[MemoryDiagnoser]
8-
[HardwareCounters(HardwareCounter.CacheMisses)]
98
public class TryGetBenchmark
109
{
10+
[Params(10000, 100000, 1000000)] public int Amount;
11+
1112
private static World _world;
1213
private static List<Entity> _entities;
1314

@@ -18,15 +19,15 @@ public void Setup()
1819
{
1920
_world = World.Create();
2021

21-
_entities = new List<Entity>(1_000_000);
22-
for (var index = 0; index < 1_000_000; index++)
22+
_entities = new List<Entity>(Amount);
23+
for (var index = 0; index < Amount; index++)
2324
{
2425
_entities.Add(_world.Create(new Transform(), new Velocity()));
2526
}
2627
}
2728

2829
[Benchmark]
29-
public void TryGetGenericRef()
30+
public void TryGetGenericRefSuccess()
3031
{
3132
for (var index = 0; index < _entities.Count; index++)
3233
{
@@ -41,7 +42,22 @@ public void TryGetGenericRef()
4142
}
4243

4344
[Benchmark]
44-
public void TryGetGeneric()
45+
public void TryGetGenericRefFail()
46+
{
47+
for (var index = 0; index < _entities.Count; index++)
48+
{
49+
var entity = _entities[index];
50+
var pos = _world.TryGetRef<Position2D>(entity, out var exists);
51+
52+
if (!exists)
53+
{
54+
_consumer.Consume(pos);
55+
}
56+
}
57+
}
58+
59+
[Benchmark]
60+
public void TryGetGenericSuccess()
4561
{
4662
for (var index = 0; index < _entities.Count; index++)
4763
{
@@ -55,16 +71,48 @@ public void TryGetGeneric()
5571
}
5672

5773
[Benchmark]
58-
public void TryGet()
74+
public void TryGetGenericFail()
75+
{
76+
for (var index = 0; index < _entities.Count; index++)
77+
{
78+
var entity = _entities[index];
79+
80+
if (!_world.TryGet<Position2D>(entity, out var pos))
81+
{
82+
_consumer.Consume(pos);
83+
}
84+
}
85+
}
86+
87+
[Benchmark]
88+
public void TryGetSuccess()
5989
{
90+
var xformType = Component.GetComponentType(typeof(Transform));
91+
6092
for (var index = 0; index < _entities.Count; index++)
6193
{
6294
var entity = _entities[index];
6395

64-
if (_world.TryGet(entity, Component.GetComponentType(typeof(Transform)), out var xform))
96+
if (_world.TryGet(entity, xformType, out var xform))
6597
{
6698
_consumer.Consume(xform);
6799
}
68100
}
69101
}
102+
103+
[Benchmark]
104+
public void TryGetFail()
105+
{
106+
var xformType = Component.GetComponentType(typeof(Position2D));
107+
108+
for (var index = 0; index < _entities.Count; index++)
109+
{
110+
var entity = _entities[index];
111+
112+
if (!_world.TryGet(entity, xformType, out var pos))
113+
{
114+
_consumer.Consume(pos);
115+
}
116+
}
117+
}
70118
}

src/Arch/Core/Archetype.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,24 @@ internal Archetype(Signature signature, int baseChunkSize, int baseChunkEntityCo
307307
internal bool TryIndex<T>(out int i)
308308
{
309309
var id = Component<T>.ComponentType.Id;
310-
Debug.Assert(id != -1, $"Index is out of bounds, component {typeof(T)} with id {id} does not exist in this chunk.");
310+
Debug.Assert(id != -1, $"Supplied component index is invalid");
311+
312+
if (id >= _componentIdToArrayIndex.Length)
313+
{
314+
i = -1;
315+
return false;
316+
}
317+
318+
i = _componentIdToArrayIndex.DangerousGetReferenceAt(id);
319+
return i != -1;
320+
}
321+
322+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
323+
[Pure]
324+
internal bool TryIndex(ComponentType type, out int i)
325+
{
326+
var id = type.Id;
327+
Debug.Assert(id != -1, $"Supplied component index is invalid");
311328

312329
if (id >= _componentIdToArrayIndex.Length)
313330
{

src/Arch/Core/World.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ public ref T Get<T>(Entity entity)
11211121
[Pure]
11221122
public bool TryGet<T>(Entity entity, out T? component)
11231123
{
1124-
ref var slot = ref EntityInfo.EntitySlots[entity.Id];
1124+
ref var slot = ref EntityInfo.EntityData[entity.Id];
11251125

11261126
if (!slot.Archetype.TryIndex<T>(out int compIndex))
11271127
{
@@ -1130,7 +1130,7 @@ public bool TryGet<T>(Entity entity, out T? component)
11301130
}
11311131

11321132
ref var chunk = ref slot.Archetype.GetChunk(slot.Slot.ChunkIndex);
1133-
Debug.Assert(compIndex != -1 && compIndex < chunk.Components.Length, $"Index is out of bounds, component {typeof(T)} with id {compIndex} does not exist in this chunk.");
1133+
Debug.Assert(compIndex != -1 && compIndex < chunk.Components.Length, $"Index is out of bounds, component {typeof(T)} with id {compIndex} does not exist in this archetype.");
11341134
var array = Unsafe.As<T[]>(chunk.Components.DangerousGetReferenceAt(compIndex));
11351135
component = array[slot.Slot.Index];
11361136
return true;
@@ -1147,7 +1147,7 @@ public bool TryGet<T>(Entity entity, out T? component)
11471147
[Pure]
11481148
public ref T TryGetRef<T>(Entity entity, out bool exists)
11491149
{
1150-
ref var slot = ref EntityInfo.EntitySlots[entity.Id];
1150+
ref var slot = ref EntityInfo.EntityData[entity.Id];
11511151

11521152
if (!(exists = slot.Archetype.Has<T>()))
11531153
{
@@ -1398,14 +1398,18 @@ public void GetRange(Entity entity, Span<ComponentType> types, Span<object?> com
13981398
[Pure]
13991399
public bool TryGet(Entity entity, ComponentType type, out object? component)
14001400
{
1401-
component = default;
1402-
if (!Has(entity, type))
1401+
ref var slot = ref EntityInfo.EntityData[entity.Id];
1402+
1403+
if (!slot.Archetype.TryIndex(type, out int compIndex))
14031404
{
1405+
component = default;
14041406
return false;
14051407
}
14061408

1407-
var entitySlot = EntityInfo.GetEntitySlot(entity.Id);
1408-
component = entitySlot.Archetype.Get(ref entitySlot.Slot, type);
1409+
ref var chunk = ref slot.Archetype.GetChunk(slot.Slot.ChunkIndex);
1410+
Debug.Assert(compIndex != -1 && compIndex < chunk.Components.Length, $"Index is out of bounds, component {type} with id {compIndex} does not exist in this archetype.");
1411+
var array = Unsafe.As<object[]>(chunk.Components.DangerousGetReferenceAt(compIndex));
1412+
component = array[slot.Slot.Index];
14091413
return true;
14101414
}
14111415

0 commit comments

Comments
 (0)