Skip to content

Commit

Permalink
Introduces a ComponentType which stores the most important component …
Browse files Browse the repository at this point in the history
…informations. This way less lookups are required which reduces adress jumping during usage. The chunk capacity calculation does not count tag components anymore, this way tags to not influence the chunks entity capacity.
  • Loading branch information
genaray committed Dec 16, 2022
1 parent 818dade commit b56ec46
Show file tree
Hide file tree
Showing 25 changed files with 196 additions and 181 deletions.
3 changes: 2 additions & 1 deletion Arch.Benchmark/ArchetypeIterationBenchmark.cs
@@ -1,6 +1,7 @@
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using Arch.Core;
using Arch.Core.Utils;
using Arch.Test;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
Expand All @@ -13,7 +14,7 @@ namespace Arch.Benchmark;
[HardwareCounters(HardwareCounter.CacheMisses)]
public class ArchetypeIterationBenchmark
{
private readonly Type[] _group = { typeof(Transform), typeof(Rotation) };
private readonly ComponentType[] _group = { typeof(Transform), typeof(Rotation) };

[Params(10000, 100000, 1000000)] public int Amount;

Expand Down
3 changes: 2 additions & 1 deletion Arch.Benchmark/ArchetypeIterationTechnqiquesBenchmark.cs
@@ -1,5 +1,6 @@
using System.Runtime.CompilerServices;
using Arch.Core;
using Arch.Core.Utils;
using Arch.Test;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
Expand All @@ -14,7 +15,7 @@ namespace Arch.Benchmark;
//[RyuJitX64Job]
public class ArchetypeIterationTechniquesBenchmark
{
private readonly Type[] _group = { typeof(Transform), typeof(Rotation) };
private readonly ComponentType[] _group = { typeof(Transform), typeof(Rotation) };

[Params(10000, 100000, 1000000, 10000000)]
public int Amount;
Expand Down
3 changes: 2 additions & 1 deletion Arch.Benchmark/QueryBenchmark.cs
@@ -1,6 +1,7 @@
using System.Runtime.CompilerServices;
using Arch.Core;
using Arch.Core.Extensions;
using Arch.Core.Utils;
using Arch.Test;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
Expand All @@ -14,7 +15,7 @@ namespace Arch.Benchmark;
[HardwareCounters(HardwareCounter.CacheMisses)]
public class QueryBenchmark
{
private readonly Type[] _group = { typeof(Transform), typeof(Velocity) };
private readonly ComponentType[] _group = { typeof(Transform), typeof(Velocity) };

[Params(10000, 100000, 1000000)] public int Amount;

Expand Down
8 changes: 5 additions & 3 deletions Arch.SourceGenerator/Fundamentals/GroupExtensions.cs
Expand Up @@ -19,17 +19,19 @@ public static StringBuilder AppendGroup(this StringBuilder sb, int amount)
var generics = new StringBuilder().GenericWithoutBrackets(amount);
var types = new StringBuilder();
for (var index = 0; index <= amount; index++)
types.Append($"typeof(T{index}),");
types.Append($"Component<T{index}>.ComponentType,");

var template = $@"
public static class Group<{generics}>
{{
internal static readonly int Id;
internal static readonly Type[] Types;
internal static readonly ComponentType[] Types;
internal static readonly int Hash;
static Group(){{
Id = Group.Id++;
Types = new Type[]{{{types}}};
Types = new ComponentType[]{{{types}}};
Hash = Component.GetHashCode(Types);
}}
}}
";
Expand Down
4 changes: 2 additions & 2 deletions Arch.SourceGenerator/Fundamentals/HasExtensions.cs
Expand Up @@ -20,7 +20,7 @@ public static StringBuilder AppendChunkHas(this StringBuilder sb, int amount)

var getIds = new StringBuilder();
for (var index = 0; index <= amount; index++)
getIds.AppendLine($"var t{index}ComponentId = ComponentMeta<T{index}>.Id;");
getIds.AppendLine($"var t{index}ComponentId = Component<T{index}>.ComponentType.Id;");

var boundChecks = new StringBuilder();
for (var index = 0; index <= amount; index++)
Expand Down Expand Up @@ -60,7 +60,7 @@ public static StringBuilder AppendArchetypeHas(this StringBuilder sb, int amount

var getIds = new StringBuilder();
for (var index = 0; index <= amount; index++)
getIds.AppendLine($"var t{index}ComponentId = ComponentMeta<T{index}>.Id;");
getIds.AppendLine($"var t{index}ComponentId = Component<T{index}>.ComponentType.Id;");

var isSet = new StringBuilder();
for (var index = 0; index <= amount; index++)
Expand Down
Expand Up @@ -22,7 +22,7 @@ public static StringBuilder AppendWorldAdd(this StringBuilder sb, int amount)

var setIds = new StringBuilder();
for (var index = 0; index <= amount; index++)
setIds.AppendLine($"ids[^{index+1}] = ComponentMeta<T{index}>.Id;");
setIds.AppendLine($"ids[^{index+1}] = Component<T{index}>.ComponentType.Id;");

var types = new StringBuilder();
for (var index = 0; index <= amount; index++)
Expand Down Expand Up @@ -66,7 +66,7 @@ public static StringBuilder AppendWorldRemove(this StringBuilder sb, int amount)

var removes = new StringBuilder();
for (var index = 0; index <= amount; index++)
removes.AppendLine($"ids.Remove(ComponentMeta<T{index}>.Id);");
removes.AppendLine($"ids.Remove(Component<T{index}>.ComponentType.Id);");

var types = new StringBuilder();
for (var index = 0; index <= amount; index++)
Expand Down
5 changes: 3 additions & 2 deletions Arch.Test/ArchetypeTest.cs
@@ -1,12 +1,13 @@
using Arch.Core;
using Arch.Core.Utils;

namespace Arch.Test;

[TestFixture]
public class ArchetypeTest
{
private readonly Type[] _group = { typeof(Transform), typeof(Rotation) };
private readonly Type[] _otherGroup = { typeof(Transform), typeof(Rotation), typeof(Ai) };
private readonly ComponentType[] _group = { typeof(Transform), typeof(Rotation) };
private readonly ComponentType[] _otherGroup = { typeof(Transform), typeof(Rotation), typeof(Ai) };

[Test]
public void CreateChunk()
Expand Down
3 changes: 2 additions & 1 deletion Arch.Test/ChunkTest.cs
@@ -1,12 +1,13 @@
using Arch.Core;
using Arch.Core.Utils;

namespace Arch.Test;

[TestFixture]
public class ChunkTest
{
private Chunk _chunk;
private readonly Type[] _types = { typeof(Transform), typeof(Rotation) };
private readonly ComponentType[] _types = { typeof(Transform), typeof(Rotation) };

[Test]
public void ArchetypeSet()
Expand Down
6 changes: 3 additions & 3 deletions Arch.Test/CommandBufferTest.cs
Expand Up @@ -10,9 +10,9 @@ namespace Arch.Test;
public partial class CommandBufferTest
{

private static readonly Type[] _group = { typeof(Transform), typeof(Rotation) };
private static readonly Type[] _secondGroup = { typeof(Transform), typeof(Rotation), typeof(Ai), typeof(int) };
private readonly QueryDescription _queryDescription = new QueryDescription { All = _group };
private static readonly ComponentType[] _group = { typeof(Transform), typeof(Rotation) };
private static readonly ComponentType[] _secondGroup = { typeof(Transform), typeof(Rotation), typeof(Ai), typeof(int) };
private readonly QueryDescription _queryDescription = new(){ All = _group };

[Test]
public void CommandBufferSparseSet()
Expand Down
10 changes: 5 additions & 5 deletions Arch.Test/ComparerTest.cs
Expand Up @@ -10,11 +10,11 @@ public class ComparerTest
public void Test()
{

var array1 = new Type[] { typeof(int), typeof(byte) };
var array2 = new Type[] { typeof(int), typeof(byte) };
var array3 = new Type[] { typeof(byte), typeof(int) };
ComponentType[] array1 = { typeof(int), typeof(byte) };
ComponentType[] array2 = { typeof(int), typeof(byte) };
ComponentType[] array3 = { typeof(byte), typeof(int) };

Assert.AreEqual(ComponentMeta.GetHashCode(array1), ComponentMeta.GetHashCode(array2));
Assert.AreEqual(ComponentMeta.GetHashCode(array1), ComponentMeta.GetHashCode(array3));
Assert.AreEqual(Component.GetHashCode(array1), Component.GetHashCode(array2));
Assert.AreEqual(Component.GetHashCode(array1), Component.GetHashCode(array3));
}
}
3 changes: 1 addition & 2 deletions Arch.Test/EntityTest.cs
Expand Up @@ -11,12 +11,11 @@ public partial class EntityTest
public void Setup()
{
_world = World.Create();
_group = new[] { typeof(Transform), typeof(Rotation) };
_entity = _world.Create(_group);
}

private World _world;
private Type[] _group;
private readonly ComponentType[] _group = { typeof(Transform), typeof(Rotation) };
private Entity _entity;

[Test]
Expand Down
15 changes: 6 additions & 9 deletions Arch.Test/EnumeratorTest.cs
@@ -1,21 +1,20 @@
using Arch.Core;
using Arch.Core.Utils;

namespace Arch.Test;

public class EnumeratorTest
{
private QueryDescription _description;
private Type[] _group;
private Type[] _otherGroup;

private static readonly ComponentType[] _group = { typeof(Transform), typeof(Rotation) };
private static readonly ComponentType[] _otherGroup = { typeof(Transform), typeof(Rotation), typeof(Ai) };
private QueryDescription _description = new() { All = _group };

private World _world;

[OneTimeSetUp]
public void Setup()
{
_group = new[] { typeof(Transform), typeof(Rotation) };
_otherGroup = new[] { typeof(Transform), typeof(Rotation), typeof(Ai) };

_world = World.Create();
_world.Reserve(_group, 10000);
_world.Reserve(_otherGroup, 10000);
Expand All @@ -25,8 +24,6 @@ public void Setup()

for (var index = 0; index < 10000; index++)
_world.Create(_otherGroup);

_description = new QueryDescription { All = _group };
}

[Test]
Expand Down Expand Up @@ -69,6 +66,6 @@ public void QueryChunkEnumeration()
foreach (ref var chunk in query.GetChunkIterator())
counter++;

Assert.AreEqual(41, counter);
Assert.AreEqual(40, counter);
}
}
17 changes: 9 additions & 8 deletions Arch.Test/QueryTest.cs
@@ -1,4 +1,5 @@
using Arch.Core;
using Arch.Core.Utils;

namespace Arch.Test;

Expand All @@ -9,11 +10,11 @@ public class QueryTest
private JobScheduler.JobScheduler _jobScheduler;
private World _world;

private readonly Type[] _entityGroup = { typeof(Transform), typeof(Rotation) };
private readonly Type[] _entityAiGroup = { typeof(Transform), typeof(Rotation), typeof(Ai) };
private static readonly ComponentType[] _entityGroup = { typeof(Transform), typeof(Rotation) };
private static readonly ComponentType[] _entityAiGroup = { typeof(Transform), typeof(Rotation), typeof(Ai) };

private readonly QueryDescription _withoutAiQuery = new() { All = new[] { typeof(Transform) }, Any = new[] { typeof(Rotation) }, None = new[] { typeof(Ai) } };
private readonly QueryDescription _allQuery = new() { All = new[] { typeof(Transform), typeof(Rotation) }, Any = new[] { typeof(Ai) } };
private readonly QueryDescription _withoutAiQuery = new() { All = new ComponentType[] { typeof(Transform) }, Any = new ComponentType[] { typeof(Rotation) }, None = new ComponentType[] { typeof(Ai) } };
private readonly QueryDescription _allQuery = new() { All = new ComponentType[] { typeof(Transform), typeof(Rotation) }, Any = new ComponentType[] { typeof(Ai) } };


[OneTimeSetUp]
Expand All @@ -31,7 +32,7 @@ public void Teardown()
[Test]
public void AllQuery()
{
var query = new QueryDescription { All = new[] { typeof(Transform) } };
var query = new QueryDescription { All = new ComponentType[] { typeof(Transform) } };

_world = World.Create();
for (var index = 0; index < 100; index++)
Expand All @@ -45,7 +46,7 @@ public void AllQuery()
[Test]
public void AnyQuery()
{
var query = new QueryDescription { Any = new[] { typeof(Transform) } };
var query = new QueryDescription { Any = new ComponentType[] { typeof(Transform) } };

_world = World.Create();
for (var index = 0; index < 100; index++)
Expand All @@ -59,7 +60,7 @@ public void AnyQuery()
[Test]
public void NoneQuery()
{
var query = new QueryDescription { None = new[] { typeof(Transform) } };
var query = new QueryDescription { None = new ComponentType[] { typeof(Transform) } };

_world = World.Create();
for (var index = 0; index < 100; index++)
Expand All @@ -73,7 +74,7 @@ public void NoneQuery()
[Test]
public void ExclusiveQuery()
{
var exclusiveGroup = new[] { typeof(Transform), typeof(Rotation) };
var exclusiveGroup = new ComponentType[] { typeof(Transform), typeof(Rotation) };
var query = new QueryDescription { Exclusive = exclusiveGroup };

_world = World.Create();
Expand Down
16 changes: 6 additions & 10 deletions Arch.Test/WorldTest.cs
Expand Up @@ -27,12 +27,8 @@ public void Teardown()

private World _world;

private readonly Type[] _entityGroup = { typeof(Transform), typeof(Rotation) };
private readonly Type[] _entityAiGroup = { typeof(Transform), typeof(Rotation), typeof(Ai) };

private QueryDescription _withoutAiQuery = new() { All = new[] { typeof(Transform) }, Any = new[] { typeof(Rotation) }, None = new[] { typeof(Ai) } };

private QueryDescription _withAiQuery = new() { All = new[] { typeof(Transform), typeof(Rotation) }, Any = new[] { typeof(Ai) } };
private readonly ComponentType[] _entityGroup = { typeof(Transform), typeof(Rotation) };
private readonly ComponentType[] _entityAiGroup = { typeof(Transform), typeof(Rotation), typeof(Ai) };

[Test]
public void Create()
Expand Down Expand Up @@ -60,7 +56,7 @@ public void Destroy()
[Test]
public void DestroyAll()
{
var query = new QueryDescription { All = new[] { typeof(Transform) } };
var query = new QueryDescription { All = new ComponentType[] { typeof(Transform) } };

var entities = new List<Entity>();
_world.GetEntities(query, entities);
Expand Down Expand Up @@ -127,8 +123,8 @@ public void Reserve()
[Test]
public void MultipleArchetypesTest()
{
var archTypes1 = new[] { typeof(Transform) };
var archTypes2 = new[] { typeof(Transform) };
var archTypes1 = new ComponentType[] { typeof(Transform) };
var archTypes2 = new ComponentType[] { typeof(Transform) };

var entity1 = _world.Create(archTypes1);
var entity2 = _world.Create(archTypes2);
Expand All @@ -141,7 +137,7 @@ public void GetEntitesTest()
{
var world = World.Create();

var archTypes = new[] { typeof(Transform) };
var archTypes = new ComponentType[] { typeof(Transform) };
var query = new QueryDescription { All = archTypes };

var entity = world.Create(archTypes);
Expand Down
8 changes: 4 additions & 4 deletions Arch/Core/Archetype.cs
Expand Up @@ -15,7 +15,7 @@ public sealed unsafe partial class Archetype
{
public const int TotalCapacity = 16000; // 16KB, fits perfectly into one L1 Cache

internal Archetype(params Type[] types)
internal Archetype(params ComponentType[] types)
{
Types = types;
EntitiesPerChunk = CalculateEntitiesPerChunk(types);
Expand All @@ -31,7 +31,7 @@ internal Archetype(params Type[] types)
/// <summary>
/// The types with which the <see cref="BitSet" /> was created.
/// </summary>
public Type[] Types { get; }
public ComponentType[] Types { get; }

/// <summary>
/// The bitmask for querying, contains the component flags set for this archetype.
Expand Down Expand Up @@ -201,7 +201,7 @@ public void Set<T>(in Entity entity, in T cmp)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has<T>()
{
var id = ComponentMeta<T>.Id;
var id = Component<T>.ComponentType.Id;
return BitSet.IsSet(id);
}

Expand Down Expand Up @@ -246,7 +246,7 @@ public Enumerator<Chunk> GetEnumerator()
/// </summary>
/// <param name="types"></param>
/// <returns></returns>
public static int CalculateEntitiesPerChunk(Type[] types)
public static int CalculateEntitiesPerChunk(ComponentType[] types)
{
return TotalCapacity / (sizeof(Entity) + types.ToByteSize());
}
Expand Down

0 comments on commit b56ec46

Please sign in to comment.