-
Notifications
You must be signed in to change notification settings - Fork 0
Benchmark Tests
Damian edited this page Jan 10, 2026
·
6 revisions
The following is a collection of Benchmark Tests to showcase release iterations.
- Executes both sync and async
- Transition Cycles: 1, 100, 1_000, 10_000
State1 -> State2 -> State3 -> [State1 -> ...]
- Sample alternate configuration
BenchmarkDotNet v0.15.8, Windows 11 (10.0.22631.6345/23H2/2023Update/SunValley3)
13th Gen Intel Core i9-13950HX 2.20GHz, 1 CPU, 32 logical and 24 physical cores
.NET SDK 10.0.101
[Host] : .NET 10.0.1 (10.0.1, 10.0.125.57005), X64 RyuJIT x86-64-v3
DefaultJob : .NET 10.0.1 (10.0.1, 10.0.125.57005), X64 RyuJIT x86-64-v3
Legends:
CyclesBeforeExit : Value of the 'CyclesBeforeExit' parameter
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)
Gen0 : GC Generation 0 collects per 1000 operations
Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
1 ns : 1 Nanosecond (0.000000001 sec)
Date: 2026-01-04
| Method | CyclesBeforeExit | Mean | Error | StdDev | Gen0 | Allocated |
|----------------------|----------------- |---------:|---------:|---------:|-------:|----------:|
| BasicStatesRunsAsync | 1 | 705.4 ns | 14.01 ns | 31.35 ns | 0.1965 | 3.62 KB |
| BasicStatesRunsSync | 1 | 702.7 ns | 9.56 ns | 8.47 ns | 0.1965 | 3.62 KB |
| BasicStatesRunsAsync | 100 | 699.1 ns | 11.94 ns | 9.32 ns | 0.1965 | 3.62 KB |
| BasicStatesRunsSync | 100 | 686.1 ns | 13.56 ns | 16.66 ns | 0.1965 | 3.62 KB |
| BasicStatesRunsAsync | 1000 | 688.5 ns | 6.22 ns | 5.20 ns | 0.1965 | 3.62 KB |
| BasicStatesRunsSync | 1000 | 667.7 ns | 6.12 ns | 5.73 ns | 0.1965 | 3.62 KB |
| BasicStatesRunsAsync | 10000 | 694.7 ns | 3.33 ns | 2.78 ns | 0.1965 | 3.62 KB |
| BasicStatesRunsSync | 10000 | 679.2 ns | 11.24 ns | 8.78 ns | 0.1965 | 3.62 KB |
Date: 2026-01-03
| Method | CyclesBeforeExit | Mean | Error | StdDev | Gen0 | Allocated |
|----------------------|----------------- |---------:|---------:|---------:|-------:|----------:|
| BasicStatesRunsAsync | 1 | 999.9 ns | 19.26 ns | 18.91 ns | 0.1926 | 3.55 KB |
| BasicStatesRunsSync | 1 | 977.8 ns | 19.57 ns | 47.25 ns | 0.1926 | 3.55 KB |
| BasicStatesRunsAsync | 100 | 738.8 ns | 14.81 ns | 32.20 ns | 0.1926 | 3.55 KB |
| BasicStatesRunsSync | 100 | 691.0 ns | 11.56 ns | 10.81 ns | 0.1926 | 3.55 KB |
| BasicStatesRunsAsync | 1000 | 702.0 ns | 7.57 ns | 6.71 ns | 0.1926 | 3.55 KB |
| BasicStatesRunsSync | 1000 | 664.2 ns | 6.05 ns | 5.66 ns | 0.1926 | 3.55 KB |
| BasicStatesRunsAsync | 10000 | 713.4 ns | 14.23 ns | 18.50 ns | 0.1926 | 3.55 KB |
| BasicStatesRunsSync | 10000 | 718.9 ns | 13.45 ns | 26.24 ns | 0.1926 | 3.55 KB |
- Date: 2026-01-10 - Improve Context
- Story: #88
| Method | CyclesBeforeExit | Mean | Error | StdDev | Gen0 | Allocated |
|--------------------- |----------------- |---------:|---------:|---------:|-------:|----------:|
| BasicStatesRunsAsync | 1 | 611.5 ns | 2.75 ns | 2.57 ns | 0.1526 | 2.81 KB |
| BasicStatesRunsSync | 1 | 608.8 ns | 5.26 ns | 4.66 ns | 0.1526 | 2.81 KB |
| BasicStatesRunsAsync | 100 | 613.9 ns | 3.59 ns | 3.35 ns | 0.1526 | 2.81 KB |
| BasicStatesRunsSync | 100 | 609.2 ns | 3.58 ns | 3.17 ns | 0.1526 | 2.81 KB |
| BasicStatesRunsAsync | 1000 | 613.9 ns | 5.39 ns | 4.78 ns | 0.1526 | 2.81 KB |
| BasicStatesRunsSync | 1000 | 606.4 ns | 5.32 ns | 4.71 ns | 0.1526 | 2.81 KB |
| BasicStatesRunsAsync | 10000 | 613.7 ns | 8.11 ns | 7.58 ns | 0.1526 | 2.81 KB |
| BasicStatesRunsSync | 10000 | 616.9 ns | 11.39 ns | 10.65 ns | 0.1526 | 2.81 KB |
Date: 2026-01-10
| Method | CyclesBeforeExit | Mean | Error | StdDev | Gen0 | Allocated |
|--------------------- |----------------- |---------:|--------:|--------:|-------:|----------:|
| BasicStatesRunsAsync | 1 | 680.2 ns | 6.87 ns | 6.43 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsSync | 1 | 664.9 ns | 2.76 ns | 2.58 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsAsync | 100 | 672.6 ns | 6.35 ns | 5.63 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsSync | 100 | 652.7 ns | 4.04 ns | 3.38 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsAsync | 1000 | 667.9 ns | 9.63 ns | 8.53 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsSync | 1000 | 662.1 ns | 6.22 ns | 5.51 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsAsync | 10000 | 669.8 ns | 6.42 ns | 6.00 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsSync | 10000 | 662.6 ns | 4.22 ns | 3.74 ns | 0.1974 | 3.64 KB |
Date: 2026-01-09
| Method | CyclesBeforeExit | Mean | Error | StdDev | Gen0 | Allocated |
|--------------------- |----------------- |---------:|---------:|---------:|-------:|----------:|
| BasicStatesRunsAsync | 1 | 743.3 ns | 13.46 ns | 11.93 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsSync | 1 | 709.5 ns | 12.86 ns | 13.76 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsAsync | 100 | 701.1 ns | 13.52 ns | 12.65 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsSync | 100 | 710.0 ns | 12.20 ns | 11.41 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsAsync | 1000 | 718.8 ns | 5.97 ns | 4.66 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsSync | 1000 | 704.2 ns | 10.97 ns | 10.26 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsAsync | 10000 | 726.3 ns | 14.33 ns | 15.33 ns | 0.1974 | 3.64 KB |
| BasicStatesRunsSync | 10000 | 725.5 ns | 11.70 ns | 10.37 ns | 0.1974 | 3.64 KB |
[GlobalSetup]
public void BasicStateGlobalSetup()
{
_machine = new StateMachine<BasicStateId>(null, null, isContextPersistent: true);
_machine.RegisterState<BasicState1>(BasicStateId.State1, BasicStateId.State2);
_machine.RegisterState<BasicState2>(BasicStateId.State2, BasicStateId.State3);
_machine.RegisterState<BasicState3>(BasicStateId.State3, onSuccess: null, onError: BasicStateId.State1);
}
[Benchmark]
public async Task BasicStatesRunsAsync()
{
var maxCounter = CyclesBeforeExit;
PropertyBag parameters = new() { { ParameterType.MaxCounter, maxCounter }, { ParameterType.Counter, 0 } };
await _machine.RunAsync(BasicStateId.State1, parameters);
}public class BasicState1 : StateBase<BasicState1, BasicStateId>;
public class BasicState2 : StateBase<BasicState2, BasicStateId>;
public class BasicState3 : StateBase<BasicState3, BasicStateId>
{
public override Task OnEnter(Context<BasicStateId> context)
{
var max = context.ParameterAsInt(ParameterType.MaxCounter);
var cnt = context.ParameterAsInt(ParameterType.Counter);
cnt++;
context.Parameters.SafeAdd(ParameterType.Counter, cnt);
if (cnt > max)
context.NextState(Result.Success);
else
context.NextState(Result.Error);
return Task.CompletedTask;
}
}