Skip to content

Commit 350989d

Browse files
author
Vyacheslav
committed
feat: resolve #48
1 parent 5e976ed commit 350989d

File tree

7 files changed

+231
-20
lines changed

7 files changed

+231
-20
lines changed

Src/Benchmarks/Stack/Optimal/ClassOptimalJob.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,21 @@ public void StackMemory()
1818
{
1919
using (var memory = new StackMemoryCollections.Struct.StackMemory(JobClassHelper.SizeOf + (JobClassHelper.SizeOf * (nuint)Size)))
2020
{
21-
var item = new Benchmark.Struct.JobClassWrapper(&memory);
21+
var item = new Benchmark.Struct.JobClassWrapper(memory.Start, false);
22+
var js2W = new Benchmark.Struct.JobClass2Wrapper(memory.Start, false);
2223
for (int j = 0; j < 100; j++)
2324
{
2425
{
2526
using var stack = new Benchmark.Struct.StackOfJobClass((nuint)Size, &memory);
2627
for (int i = 0; i < Size; i++)
2728
{
29+
item.ChangePtr(stack.TopFuture());
2830
item.Int32 = i;
2931
item.Int64 = i * 2;
30-
var jc2 = Benchmark.JobClassHelper.GetJobClass2Ptr(item.Ptr);
31-
Benchmark.JobClass2Helper.SetInt32Value(in jc2, i + 3);
32-
Benchmark.JobClass2Helper.SetInt64Value(in jc2, i * 3);
33-
stack.Push(item.Ptr);
32+
js2W.ChangePtr(item.JobClass2Ptr);
33+
js2W.Int32 = i + 3;
34+
js2W.Int64 = i * 3;
35+
stack.PushFuture();
3436
}
3537

3638
if(j > 50)
@@ -48,12 +50,13 @@ public void StackMemory()
4850
using var stack2 = new Benchmark.Struct.StackOfJobClass((nuint)Size, &memory);
4951
for (int i = 0; i < Size; i++)
5052
{
53+
item.ChangePtr(stack2.TopFuture());
5154
item.Int32 = i;
5255
item.Int64 = i * 2;
53-
var jc2 = Benchmark.JobClassHelper.GetJobClass2Ptr(item.Ptr);
54-
Benchmark.JobClass2Helper.SetInt32Value(in jc2, i + 3);
55-
Benchmark.JobClass2Helper.SetInt64Value(in jc2, i * 3);
56-
stack2.Push(item.Ptr);
56+
js2W.ChangePtr(item.JobClass2Ptr);
57+
js2W.Int32 = i + 3;
58+
js2W.Int64 = i * 3;
59+
stack2.PushFuture();
5760
}
5861

5962
if (j > 50)

Src/Benchmarks/Stack/Optimal/PrimitiveOptimalJob.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public void StackMemory()
2424
using var stack = new StackMemoryCollections.Struct.StackOfInt32((nuint)Size, &memory);
2525
for (int i = 0; i < Size; i++)
2626
{
27-
stack.Push(in i);
27+
*stack.TopFuture() = i;
2828
}
2929

3030
if(j > 50)
@@ -42,7 +42,7 @@ public void StackMemory()
4242
using var stack2 = new StackMemoryCollections.Struct.StackOfInt32((nuint)Size, &memory);
4343
for (int i = 0; i < Size; i++)
4444
{
45-
stack2.Push(in i);
45+
*stack2.TopFuture() = i;
4646
}
4747

4848
if (j > 50)

Src/Benchmarks/Stack/Optimal/StructOptimalJob.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,21 @@ public void StackMemory()
1818
{
1919
using (var memory = new StackMemoryCollections.Struct.StackMemory(JobStructHelper.SizeOf * (nuint)Size))
2020
{
21-
var item = new JobStruct(0, 0);
21+
var item = new Benchmark.Struct.JobStructWrapper(memory.Start, false);
22+
var js2W = new Benchmark.Struct.JobStruct2Wrapper(memory.Start, false);
2223
for (int j = 0; j < 100; j++)
2324
{
2425
{
2526
using var stack = new Benchmark.Struct.StackOfJobStruct((nuint)Size, &memory);
2627
for (int i = 0; i < Size; i++)
2728
{
29+
item.ChangePtr(stack.TopFuture());
2830
item.Int32 = i;
2931
item.Int64 = i * 2;
30-
item.JobStruct2.Int32 = 15;
31-
item.JobStruct2.Int64 = 36;
32-
stack.Push(in item);
32+
js2W.ChangePtr(item.JobStruct2Ptr);
33+
js2W.Int32 = 15;
34+
js2W.Int64 = 36;
35+
stack.PushFuture();
3336
}
3437

3538
if(j > 50)
@@ -47,11 +50,13 @@ public void StackMemory()
4750
using var stack2 = new Benchmark.Struct.StackOfJobStruct((nuint)Size, &memory);
4851
for (int i = 0; i < Size; i++)
4952
{
53+
item.ChangePtr(stack2.TopFuture());
5054
item.Int32 = i;
5155
item.Int64 = i * 2;
52-
item.JobStruct2.Int32 = 15;
53-
item.JobStruct2.Int64 = 36;
54-
stack2.Push(in item);
56+
js2W.ChangePtr(item.JobStruct2Ptr);
57+
js2W.Int32 = 15;
58+
js2W.Int64 = 36;
59+
stack2.PushFuture();
5560
}
5661

5762
if (j > 50)

Src/StackMemoryCollections/GeneratePrimitiveStack.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ bool calculateSize
7676
StackPrimitiveExpandCapacity<T>(in builder, in sizeOf, calculateSize);
7777
StackPrimitiveTrimExcess(in builder);
7878
StackPrimitivePushIn<T>(in builder, in stackNamespace, in sizeOf, calculateSize);
79+
StackPrimitivePushFuture(in builder, in stackNamespace);
7980
StackPrimitivePushInPtr<T>(in builder, in stackNamespace, in sizeOf, calculateSize);
8081
StackPrimitiveTryPushIn<T>(in builder, in stackNamespace, in sizeOf, calculateSize);
8182
StackPrimitiveTryPushInPtr<T>(in builder, in stackNamespace, in sizeOf, calculateSize);
@@ -86,6 +87,7 @@ bool calculateSize
8687
StackPrimitiveTopInPtr<T>(in builder);
8788
StackPrimitiveTopRefValue<T>(in builder);
8889
StackPrimitiveTopPtr<T>(in builder);
90+
StackPrimitiveTopFuture<T>(in builder);
8991
StackPrimitiveDispose<T>(in builder, in stackNamespace, in sizeOf, calculateSize);
9092
StackPrimitiveIndexator<T>(in builder);
9193
StackPrimitiveCopyCount<T>(in builder, in sizeOf, calculateSize);
@@ -445,6 +447,32 @@ public void Push(in {typeof(T).Name} item)
445447
");
446448
}
447449

450+
private void StackPrimitivePushFuture(
451+
in StringBuilder builder,
452+
in string stackNamespace
453+
)
454+
{
455+
builder.Append($@"
456+
public void PushFuture()
457+
{{
458+
if (Size == Capacity)
459+
{{
460+
throw new Exception(""Not enough memory to allocate stack element"");
461+
}}
462+
463+
Size++;
464+
");
465+
if (stackNamespace == "Class")
466+
{
467+
builder.Append($@"
468+
_version++;
469+
");
470+
}
471+
builder.Append($@"
472+
}}
473+
");
474+
}
475+
448476
private void StackPrimitivePushInPtr<T>(
449477
in StringBuilder builder,
450478
in string stackNamespace,
@@ -735,6 +763,24 @@ in StringBuilder builder
735763
");
736764
}
737765

766+
private void StackPrimitiveTopFuture<T>(
767+
in StringBuilder builder
768+
) where T : unmanaged
769+
{
770+
builder.Append($@"
771+
public {typeof(T).Name}* TopFuture()
772+
{{
773+
if (Capacity == 0 || Size == Capacity)
774+
{{
775+
throw new Exception(""Future element not available"");
776+
}}
777+
778+
return
779+
_start + Size;
780+
}}
781+
");
782+
}
783+
738784
private void StackPrimitiveTopInPtr<T>(
739785
in StringBuilder builder
740786
) where T : unmanaged

Src/StackMemoryCollections/GenerateStack.cs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ in string stackNamespace
5050
StackExpandCapacity(in builder, in sizeOfStr);
5151
StackTrimExcess(in builder);
5252
StackPushIn(in builder, in currentType, in stackNamespace, in sizeOfStr);
53+
StackPushFuture(in builder, in stackNamespace);
5354
StackPushInPtr(in builder, in currentType, in stackNamespace, in sizeOfStr);
5455
StackTryPushIn(in builder, in currentType, in stackNamespace, in sizeOfStr);
5556
StackTryPushInPtr(in builder, in currentType, in stackNamespace, in sizeOfStr);
@@ -59,7 +60,8 @@ in string stackNamespace
5960
StackTop(in builder, in currentType, in typeInfo, in sizeOfStr);
6061
StackTopInPtr(in builder, in currentType, in sizeOfStr);
6162
StackTopRefValue(in builder, in currentType, in sizeOfStr);
62-
StackTopPtr(in builder, in typeInfo, in sizeOfStr);
63+
StackTopPtr(in builder, in sizeOfStr);
64+
StackTopFuture(in builder, in sizeOfStr);
6365
StackDispose(in builder, in currentType, in stackNamespace, in sizeOfStr);
6466
StackIndexator(in builder, in sizeOfStr);
6567
StackCopy(in builder, in sizeOfStr);
@@ -420,6 +422,32 @@ public void Push(in {currentType.Name} item)
420422
");
421423
}
422424

425+
private void StackPushFuture(
426+
in StringBuilder builder,
427+
in string stackNamespace
428+
)
429+
{
430+
builder.Append($@"
431+
public void PushFuture()
432+
{{
433+
if (Size == Capacity)
434+
{{
435+
throw new Exception(""Not enough memory to allocate stack element"");
436+
}}
437+
438+
Size++;
439+
");
440+
if (stackNamespace == "Class")
441+
{
442+
builder.Append($@"
443+
_version++;
444+
");
445+
}
446+
builder.Append($@"
447+
}}
448+
");
449+
}
450+
423451
private void StackPushInPtr(
424452
in StringBuilder builder,
425453
in INamedTypeSymbol currentType,
@@ -796,7 +824,6 @@ public void TopOut(out {currentType.Name} item)
796824

797825
private void StackTopPtr(
798826
in StringBuilder builder,
799-
in TypeInfo typeInfo,
800827
in string sizeOfStr
801828
)
802829
{
@@ -813,6 +840,24 @@ in string sizeOfStr
813840
");
814841
}
815842

843+
private void StackTopFuture(
844+
in StringBuilder builder,
845+
in string sizeOfStr
846+
)
847+
{
848+
builder.Append($@"
849+
public void* TopFuture()
850+
{{
851+
if (Capacity == 0 || Size == Capacity)
852+
{{
853+
throw new Exception(""Future element not available"");
854+
}}
855+
856+
return (byte*)_start + (Size * {sizeOfStr});
857+
}}
858+
");
859+
}
860+
816861
private void StackDispose(
817862
in StringBuilder builder,
818863
in INamedTypeSymbol currentType,

Src/TestGenerator/GenerateStackPrimitiveTest.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ in Func<T, string> toStr
267267
StackPrimitiveNotDispose(in values, in builder, in stackNamespace);
268268
StackPrimitiveReseize(in values, in builder, in stackNamespace, in toStr);
269269
StackPrimitivePush(in values, in builder, in stackNamespace, in toStr);
270+
StackPrimitivePushFuture(in values, in builder, in stackNamespace, in toStr);
270271
StackPrimitivePushPtr(in values, in builder, in stackNamespace, in toStr);
271272
StackPrimitiveTryPush(in values, in builder, in stackNamespace, in toStr);
272273
StackPrimitiveTryPushPtr(in values, in builder, in stackNamespace, in toStr);
@@ -462,6 +463,60 @@ public void PushTest()
462463
");
463464
}
464465

466+
private void StackPrimitivePushFuture<T>(
467+
in List<T> values,
468+
in StringBuilder builder,
469+
in string stackNamespace,
470+
in Func<T, string> toStr
471+
) where T : unmanaged
472+
{
473+
if (values.Count < 5)
474+
{
475+
throw new ArgumentException($"{nameof(values)} Must have minimum 5 values to generate tests");
476+
}
477+
478+
builder.Append($@"
479+
[Test]
480+
public void PushFutureTest()
481+
{{
482+
unsafe
483+
{{
484+
using (var memory = new StackMemoryCollections.Struct.StackMemory(sizeof({typeof(T).Name}) * {values.Count}))
485+
{{
486+
Assert.That(new IntPtr(memory.Current), Is.EqualTo(new IntPtr(memory.Start)));
487+
var stack = new StackMemoryCollections.{stackNamespace}.StackOf{typeof(T).Name}({values.Count}, &memory);
488+
Assert.That(new IntPtr(memory.Current), Is.EqualTo(new IntPtr(({typeof(T).Name}*)memory.Start + {values.Count})));
489+
Assert.That(stack.IsEmpty, Is.EqualTo(true));
490+
");
491+
for (int i = 0; i < values.Count; i++)
492+
{
493+
builder.Append($@"
494+
495+
*stack.TopFuture() = {toStr(values[i])};
496+
stack.PushFuture();
497+
Assert.That(stack.IsEmpty, Is.EqualTo(false));
498+
Assert.That(stack.Capacity, Is.EqualTo((nuint){values.Count}));
499+
Assert.That(stack.Size, Is.EqualTo((nuint){i + 1}));
500+
Assert.That(stack.Top(), Is.EqualTo({toStr(values[i])}));
501+
");
502+
}
503+
504+
builder.Append($@"
505+
Assert.That(() => stack.TopFuture(),
506+
Throws.Exception.TypeOf(typeof(Exception))
507+
.And.Message.EqualTo(""Future element not available"")
508+
);
509+
510+
Assert.That(() => stack.PushFuture(),
511+
Throws.Exception.TypeOf(typeof(Exception))
512+
.And.Message.EqualTo(""Not enough memory to allocate stack element"")
513+
);
514+
}}
515+
}}
516+
}}
517+
");
518+
}
519+
465520
private void StackPrimitivePushPtr<T>(
466521
in List<T> values,
467522
in StringBuilder builder,

Src/Tests/StackOfTestStructFixture.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,63 @@ public void PushTest()
164164
}
165165
}
166166

167+
[Test]
168+
public void PushFutureTest()
169+
{
170+
unsafe
171+
{
172+
using (var memory = new StackMemoryCollections.Struct.StackMemory(TestStructHelper.SizeOf * 5))
173+
{
174+
Assert.That(new IntPtr(memory.Current), Is.EqualTo(new IntPtr(memory.Start)));
175+
var stack = new Tests.Struct.StackOfTestStruct(5, &memory);
176+
Assert.That(new IntPtr(memory.Current), Is.EqualTo(new IntPtr((byte*)memory.Start + (TestStructHelper.SizeOf * 5))));
177+
Assert.That(stack.IsEmpty, Is.EqualTo(true));
178+
179+
Assert.That(new IntPtr(stack.TopFuture()), Is.EqualTo(new IntPtr((byte*)memory.Start)));
180+
stack.PushFuture();
181+
Assert.That(stack.IsEmpty, Is.EqualTo(false));
182+
Assert.That(stack.Capacity, Is.EqualTo((nuint)5));
183+
Assert.That(stack.Size, Is.EqualTo((nuint)1));
184+
185+
Assert.That(new IntPtr(stack.TopFuture()), Is.EqualTo(new IntPtr((byte*)memory.Start + (TestStructHelper.SizeOf * 1))));
186+
stack.PushFuture();
187+
Assert.That(stack.IsEmpty, Is.EqualTo(false));
188+
Assert.That(stack.Capacity, Is.EqualTo((nuint)5));
189+
Assert.That(stack.Size, Is.EqualTo((nuint)2));
190+
191+
Assert.That(new IntPtr(stack.TopFuture()), Is.EqualTo(new IntPtr((byte*)memory.Start + (TestStructHelper.SizeOf * 2))));
192+
stack.PushFuture();
193+
Assert.That(stack.IsEmpty, Is.EqualTo(false));
194+
Assert.That(stack.Capacity, Is.EqualTo((nuint)5));
195+
Assert.That(stack.Size, Is.EqualTo((nuint)3));
196+
197+
Assert.That(new IntPtr(stack.TopFuture()), Is.EqualTo(new IntPtr((byte*)memory.Start + (TestStructHelper.SizeOf * 3))));
198+
stack.PushFuture();
199+
Assert.That(stack.IsEmpty, Is.EqualTo(false));
200+
Assert.That(stack.Capacity, Is.EqualTo((nuint)5));
201+
Assert.That(stack.Size, Is.EqualTo((nuint)4));
202+
203+
204+
Assert.That(new IntPtr(stack.TopFuture()), Is.EqualTo(new IntPtr((byte*)memory.Start + (TestStructHelper.SizeOf * 4))));
205+
stack.PushFuture();
206+
Assert.That(stack.IsEmpty, Is.EqualTo(false));
207+
Assert.That(stack.Capacity, Is.EqualTo((nuint)5));
208+
Assert.That(stack.Size, Is.EqualTo((nuint)5));
209+
210+
211+
Assert.That(() => stack.TopFuture(),
212+
Throws.Exception.TypeOf(typeof(Exception))
213+
.And.Message.EqualTo("Future element not available")
214+
);
215+
216+
Assert.That(() => stack.PushFuture(),
217+
Throws.Exception.TypeOf(typeof(Exception))
218+
.And.Message.EqualTo("Not enough memory to allocate stack element")
219+
);
220+
}
221+
}
222+
}
223+
167224
[Test]
168225
public void PushNullTest()
169226
{

0 commit comments

Comments
 (0)