Skip to content

Commit f93d9a9

Browse files
committed
optimize to favor efficiency in frequently used code
1 parent 1915876 commit f93d9a9

44 files changed

Lines changed: 2409 additions & 2243 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/Chunk.cs

Lines changed: 119 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Diagnostics;
33
using System.Runtime.CompilerServices;
4+
using System.Runtime.Intrinsics;
45
using Unmanaged;
56
using Worlds.Pointers;
67

@@ -12,7 +13,18 @@ namespace Worlds
1213
[SkipLocalsInit]
1314
public unsafe struct Chunk : IDisposable, IEquatable<Chunk>
1415
{
16+
/// <summary>
17+
/// Retrieves the component types stored in this chunk.
18+
/// </summary>
19+
public readonly BitMask componentTypes;
20+
1521
internal ChunkPointer* chunk;
22+
internal uint* componentOffsets;
23+
24+
/// <summary>
25+
/// Retrieves the tag types stored in this chunk.
26+
/// </summary>
27+
public readonly BitMask tagTypes;
1628

1729
/// <summary>
1830
/// Checks if this chunk is disposed.
@@ -29,6 +41,7 @@ public unsafe struct Chunk : IDisposable, IEquatable<Chunk>
2941
/// </summary>
3042
public readonly ReadOnlySpan<uint> Entities
3143
{
44+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3245
get
3346
{
3447
MemoryAddress.ThrowIfDefault(chunk);
@@ -38,68 +51,69 @@ public readonly ReadOnlySpan<uint> Entities
3851
}
3952

4053
/// <summary>
41-
/// Amount of entities stored in this chunk.
54+
/// Retrieves the array types stored in this chunk.
4255
/// </summary>
43-
public readonly int Count
56+
public readonly BitMask ArrayTypes
4457
{
58+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
4559
get
4660
{
4761
MemoryAddress.ThrowIfDefault(chunk);
4862

49-
return chunk->count;
63+
return chunk->arrayTypes;
5064
}
5165
}
5266

5367
/// <summary>
54-
/// Returns the definition representing the types of components, arrays and tags
55-
/// this chunk is for.
68+
/// Amount of entities stored in this chunk.
5669
/// </summary>
57-
public readonly Definition Definition
70+
public readonly int Count
5871
{
72+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5973
get
6074
{
6175
MemoryAddress.ThrowIfDefault(chunk);
6276

63-
return chunk->Definition;
77+
return chunk->count;
6478
}
6579
}
6680

6781
/// <summary>
68-
/// Retrieves the component types stored in this chunk.
82+
/// Checks if this definition describes a disabled entity.
6983
/// </summary>
70-
public readonly BitMask ComponentTypes
84+
public readonly bool IsDisabled
7185
{
86+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7287
get
7388
{
74-
MemoryAddress.ThrowIfDefault(chunk);
75-
76-
return chunk->componentTypes;
89+
return (tagTypes.value.GetElement(3) & Schema.DisabledMask) != 0;
7790
}
7891
}
7992

8093
/// <summary>
81-
/// Retrieves the array types stored in this chunk.
94+
/// Checks if this definition describes an enabled entity.
8295
/// </summary>
83-
public readonly BitMask ArrayTypes
96+
public readonly bool IsEnabled
8497
{
98+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8599
get
86100
{
87-
MemoryAddress.ThrowIfDefault(chunk);
88-
89-
return chunk->arrayTypes;
101+
return (tagTypes.value.GetElement(3) & Schema.DisabledMask) == 0;
90102
}
91103
}
92104

93105
/// <summary>
94-
/// Retrieves the tag types stored in this chunk.
106+
/// Returns the definition representing the types of components, arrays and tags
107+
/// this chunk is for.
95108
/// </summary>
96-
public readonly BitMask TagTypes
109+
public readonly Definition Definition
97110
{
111+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
98112
get
99113
{
100114
MemoryAddress.ThrowIfDefault(chunk);
101115

102-
return chunk->tagTypes;
116+
return new(componentTypes, ArrayTypes, tagTypes);
103117
}
104118
}
105119

@@ -108,12 +122,12 @@ public readonly BitMask TagTypes
108122
/// </summary>
109123
public readonly Row this[int index]
110124
{
125+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
111126
get
112127
{
113128
MemoryAddress.ThrowIfDefault(chunk);
114129

115-
MemoryAddress row = chunk->components[index];
116-
return new Row(chunk->schema, row);
130+
return new Row(componentOffsets, chunk->schema.schema->sizes, chunk->components[index]);
117131
}
118132
}
119133

@@ -122,6 +136,7 @@ public readonly Row this[int index]
122136
/// </summary>
123137
public readonly int Version
124138
{
139+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
125140
get
126141
{
127142
MemoryAddress.ThrowIfDefault(chunk);
@@ -133,34 +148,81 @@ public readonly int Version
133148
#if NET
134149
/// <inheritdoc/>
135150
[Obsolete("Default constructor not supported", true)]
136-
public Chunk()
137-
{
138-
throw new NotSupportedException();
139-
}
151+
public Chunk() { }
140152
#endif
141153

142154
/// <summary>
143155
/// Creates a new chunk with the given <paramref name="definition"/>.
144156
/// </summary>
145157
public Chunk(Schema schema, Definition definition = default)
146158
{
159+
componentOffsets = schema.componentOffsets;
160+
MemoryAddress.ThrowIfDefault(componentOffsets);
161+
147162
chunk = MemoryAddress.AllocatePointer<ChunkPointer>();
148163
chunk->lastEntity = 0;
149164
chunk->count = 0;
150165
chunk->version = 0;
151166
chunk->entities = new(4);
152-
chunk->entities.AddDefault(); //reserved
167+
chunk->entities.AddDefault(); // reserved
153168
chunk->components = new(4, (int)schema.schema->componentRowSize);
154-
chunk->components.AddDefault(); //reserved
169+
chunk->components.AddDefault(); // reserved
155170
chunk->schema = schema;
156171
chunk->componentTypes = definition.componentTypes;
157172
chunk->arrayTypes = definition.arrayTypes;
158173
chunk->tagTypes = definition.tagTypes;
174+
componentTypes = definition.componentTypes;
175+
tagTypes = definition.tagTypes;
176+
}
177+
178+
internal Chunk(SchemaPointer* schema, BitMask componentTypes, BitMask arrayTypes, BitMask tagTypes)
179+
{
180+
componentOffsets = schema->componentOffsets;
181+
MemoryAddress.ThrowIfDefault(componentOffsets);
182+
183+
chunk = MemoryAddress.AllocatePointer<ChunkPointer>();
184+
chunk->lastEntity = 0;
185+
chunk->count = 0;
186+
chunk->version = 0;
187+
chunk->entities = new(4);
188+
chunk->entities.AddDefault(); // reserved
189+
chunk->components = new(4, (int)schema->componentRowSize);
190+
chunk->components.AddDefault(); // reserved
191+
chunk->schema = new(schema);
192+
chunk->componentTypes = componentTypes;
193+
chunk->arrayTypes = arrayTypes;
194+
chunk->tagTypes = tagTypes;
195+
this.componentTypes = componentTypes;
196+
this.tagTypes = tagTypes;
197+
}
198+
199+
internal Chunk(SchemaPointer* schema)
200+
{
201+
componentOffsets = schema->componentOffsets;
202+
MemoryAddress.ThrowIfDefault(componentOffsets);
203+
204+
chunk = MemoryAddress.AllocatePointer<ChunkPointer>();
205+
chunk->lastEntity = 0;
206+
chunk->count = 0;
207+
chunk->version = 0;
208+
chunk->entities = new(4);
209+
chunk->entities.AddDefault(); // reserved
210+
chunk->components = new(4, (int)schema->componentRowSize);
211+
chunk->components.AddDefault(); // reserved
212+
chunk->schema = new(schema);
213+
chunk->componentTypes = default;
214+
chunk->arrayTypes = default;
215+
chunk->tagTypes = default;
216+
componentTypes = default;
217+
tagTypes = default;
159218
}
160219

161220
internal Chunk(ChunkPointer* chunk)
162221
{
163222
this.chunk = chunk;
223+
componentTypes = chunk->componentTypes;
224+
tagTypes = chunk->tagTypes;
225+
componentOffsets = chunk->schema.componentOffsets;
164226
}
165227

166228
/// <inheritdoc/>
@@ -173,17 +235,17 @@ public void Dispose()
173235
MemoryAddress.Free(ref chunk);
174236
}
175237

176-
internal readonly void UpdateStrideToMatchSchema()
238+
internal readonly void UpdateStrideToMatchSchema(uint componentRowSize)
177239
{
178240
chunk->components.Dispose();
179-
chunk->components = new(4, (int)chunk->schema.schema->componentRowSize);
180-
chunk->components.AddDefault(); //reserved
241+
chunk->components = new(4, (int)componentRowSize);
242+
chunk->components.AddDefault(); // reserved
181243
}
182244

183245
[Conditional("DEBUG")]
184246
private readonly void ThrowIfComponentTypeIsMissing(int componentType)
185247
{
186-
if (!chunk->componentTypes.Contains(componentType))
248+
if (!componentTypes.Contains(componentType))
187249
{
188250
throw new ArgumentException($"Component type `{DataType.GetComponent(componentType, chunk->schema).ToString(chunk->schema)}` is missing from the chunk");
189251
}
@@ -221,10 +283,10 @@ public readonly int ToString(Span<char> destination)
221283
{
222284
int length = 0;
223285
length += chunk->count.ToString(destination);
224-
if (chunk->Definition != Definition.Default)
286+
if (componentTypes != BitMask.Default && ArrayTypes != BitMask.Default && tagTypes != BitMask.Default)
225287
{
226288
destination[length++] = ' ';
227-
length += chunk->Definition.ToString(chunk->schema, destination.Slice(length));
289+
length += new Definition(componentTypes, ArrayTypes, tagTypes).ToString(chunk->schema, destination.Slice(length));
228290
}
229291

230292
return length;
@@ -233,39 +295,46 @@ public readonly int ToString(Span<char> destination)
233295
/// <inheritdoc/>
234296
public readonly override int GetHashCode()
235297
{
236-
return chunk->Definition.GetHashCode();
298+
return (int)Definition.GetLongHashCode(componentTypes, ArrayTypes, tagTypes);
237299
}
238300

239301
/// <summary>
240302
/// Retrieves the byte offset of the <paramref name="componentType"/>
241303
/// </summary>
304+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
242305
public readonly int GetComponentOffset(int componentType)
243306
{
244-
MemoryAddress.ThrowIfDefault(chunk);
307+
MemoryAddress.ThrowIfDefault(componentOffsets);
308+
ThrowIfComponentTypeIsMissing(componentType);
245309

246-
return (int)chunk->schema.schema->componentOffsets[(uint)componentType];
310+
return (int)componentOffsets[(uint)componentType];
247311
}
248312

249313
/// <summary>
250314
/// Retrieves an enumerator for iterating through each component of type <typeparamref name="T"/>.
251315
/// </summary>
316+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
252317
public readonly ComponentEnumerator<T> GetComponents<T>(int componentType) where T : unmanaged
253318
{
254-
int componentOffset = (int)chunk->schema.schema->componentOffsets[(uint)componentType];
255-
return new(chunk->components, componentOffset);
319+
MemoryAddress.ThrowIfDefault(chunk);
320+
MemoryAddress.ThrowIfDefault(componentOffsets);
321+
ThrowIfComponentTypeIsMissing(componentType);
322+
323+
return new(chunk->components, (int)componentOffsets[(uint)componentType]);
256324
}
257325

258326
/// <summary>
259327
/// Retrieves a reference to the component of type <paramref name="componentType"/>.
260328
/// </summary>
329+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
261330
public readonly ref T GetComponent<T>(int index, int componentType) where T : unmanaged
262331
{
263332
MemoryAddress.ThrowIfDefault(chunk);
333+
MemoryAddress.ThrowIfDefault(componentOffsets);
264334
ThrowIfIndexIsOutOfRange(index);
265335
ThrowIfComponentTypeIsMissing(componentType);
266336

267-
int componentOffset = (int)chunk->schema.schema->componentOffsets[(uint)componentType];
268-
return ref chunk->components[index].Read<T>(componentOffset);
337+
return ref chunk->components[index].Read<T>((int)componentOffsets[(uint)componentType]);
269338
}
270339

271340
/// <inheritdoc/>
@@ -297,12 +366,14 @@ public readonly bool Equals(Chunk other)
297366
/// </summary>
298367
public readonly struct Row
299368
{
300-
private readonly Schema schema;
369+
private readonly uint* componentOffsets;
370+
private readonly int* componentSizes;
301371
internal readonly MemoryAddress row;
302372

303-
internal Row(Schema schema, MemoryAddress row)
373+
internal Row(uint* componentOffsets, int* componentSizes, MemoryAddress row)
304374
{
305-
this.schema = schema;
375+
this.componentOffsets = componentOffsets;
376+
this.componentSizes = componentSizes;
306377
this.row = row;
307378
}
308379

@@ -311,31 +382,31 @@ internal Row(Schema schema, MemoryAddress row)
311382
/// </summary>
312383
public readonly MemoryAddress GetComponent(int componentType)
313384
{
314-
return new(row.pointer + schema.schema->componentOffsets[(uint)componentType]);
385+
return new(row.pointer + componentOffsets[(uint)componentType]);
315386
}
316387

317388
/// <summary>
318389
/// Retrieves the component of type <typeparamref name="T"/>.
319390
/// </summary>
320391
public readonly ref T GetComponent<T>(int componentType) where T : unmanaged
321392
{
322-
return ref *(T*)(row.pointer + schema.schema->componentOffsets[(uint)componentType]);
393+
return ref *(T*)(row.pointer + componentOffsets[(uint)componentType]);
323394
}
324395

325396
/// <summary>
326397
/// Assigns the component of type <typeparamref name="T"/> to <paramref name="value"/>.
327398
/// </summary>
328399
public readonly void SetComponent<T>(int componentType, T value) where T : unmanaged
329400
{
330-
*(T*)(row.pointer + schema.schema->componentOffsets[(uint)componentType]) = value;
401+
*(T*)(row.pointer + componentOffsets[(uint)componentType]) = value;
331402
}
332403

333404
/// <summary>
334405
/// Retrieves all bytes for the given <paramref name="componentType"/>.
335406
/// </summary>
336407
public readonly Span<byte> GetSpan(int componentType)
337408
{
338-
return new Span<byte>(row.pointer + schema.schema->componentOffsets[(uint)componentType], schema.schema->sizes[(uint)componentType]);
409+
return new Span<byte>(row.pointer + componentOffsets[(uint)componentType], componentSizes[(uint)componentType]);
339410
}
340411
}
341412

core/ChunkKey.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
{
33
internal readonly struct ChunkKey
44
{
5-
public readonly Definition definition;
5+
public readonly long definitionHash;
66
public readonly Chunk chunk;
77

8-
public unsafe ChunkKey(Chunk chunk)
8+
public ChunkKey(Chunk chunk)
99
{
10-
this.definition = chunk.chunk->Definition;
10+
definitionHash = Definition.GetLongHashCode(chunk.componentTypes, chunk.ArrayTypes, chunk.tagTypes);
1111
this.chunk = chunk;
1212
}
1313
}

0 commit comments

Comments
 (0)