Skip to content

Commit 3ea7c6e

Browse files
Merge pull request #54 from salihcantekin/feature/benchmarks
Refactor benchmarks and simplify infrastructure
2 parents cd17753 + 0511ceb commit 3ea7c6e

12 files changed

+139
-191
lines changed

.github/workflows/benchmark.yml

Lines changed: 0 additions & 79 deletions
This file was deleted.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Benchmark Run
2+
3+
- Date (Local UTC format): 2025-09-12 21:57:44Z
4+
- Output Directory: V:\Projects\Space\SpaceSolution\tests\Space.Benchmarks\BenchmarkResults\2025-09-12
5+
6+
## System Info
7+
- OS: Microsoft Windows 10.0.26100
8+
- OS Architecture: X64
9+
- Process Architecture: X64
10+
- .NET Runtime: .NET 8.0.19
11+
- CPU Logical Cores: 32
12+
13+
## Reports
14+
The files below have been generated by benchmark tests:
15+
16+
- HandlerOnlyBench-20250912-215517-report-github.md
17+
- HandlerWithPipelineBench-20250912-215553-report-github.md
18+
- NotificationsSequentialBench-20250912-215641-report-github.md
19+
- Space.Benchmarks.Notification.NotificationsParallelBench-20250912-215722-report-github.md
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
```
2+
3+
BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley)
4+
Unknown processor
5+
.NET SDK 10.0.100-rc.1.25451.107
6+
[Host] : .NET 8.0.19 (8.0.1925.36514), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
7+
DefaultJob : .NET 8.0.19 (8.0.1925.36514), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
8+
9+
10+
```
11+
| Method | Mean | Error | StdDev | Gen0 | Allocated |
12+
|-------------- |----------:|---------:|---------:|-------:|----------:|
13+
| Space_Send | 33.25 ns | 0.341 ns | 0.303 ns | - | - |
14+
| Mediator_Send | 17.52 ns | 0.075 ns | 0.066 ns | 0.0014 | 24 B |
15+
| MediatR_Send | 252.41 ns | 2.679 ns | 2.375 ns | 0.0901 | 1512 B |
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
```
2+
3+
BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley)
4+
Unknown processor
5+
.NET SDK 10.0.100-rc.1.25451.107
6+
[Host] : .NET 8.0.19 (8.0.1925.36514), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
7+
DefaultJob : .NET 8.0.19 (8.0.1925.36514), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
8+
9+
10+
```
11+
| Method | Mean | Error | StdDev | Gen0 | Allocated |
12+
|--------------------------- |----------:|---------:|---------:|-------:|----------:|
13+
| Space_Send_WithPipeline | 52.65 ns | 0.694 ns | 0.649 ns | - | - |
14+
| Mediator_Send_WithBehavior | 20.35 ns | 0.184 ns | 0.172 ns | 0.0014 | 24 B |
15+
| MediatR_Send_WithBehavior | 273.18 ns | 4.822 ns | 6.270 ns | 0.0973 | 1632 B |
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
```
2+
3+
BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley)
4+
Unknown processor
5+
.NET SDK 10.0.100-rc.1.25451.107
6+
[Host] : .NET 8.0.19 (8.0.1925.36514), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
7+
DefaultJob : .NET 8.0.19 (8.0.1925.36514), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
8+
9+
10+
```
11+
| Method | Mean | Error | StdDev | Gen0 | Allocated |
12+
|----------------- |---------:|---------:|---------:|-------:|----------:|
13+
| Space_Publish | 42.74 ns | 0.301 ns | 0.251 ns | - | - |
14+
| Mediator_Publish | 19.35 ns | 0.149 ns | 0.124 ns | - | - |
15+
| MediatR_Publish | 76.07 ns | 0.820 ns | 0.727 ns | 0.0238 | 400 B |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
```
2+
3+
BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley)
4+
Unknown processor
5+
.NET SDK 10.0.100-rc.1.25451.107
6+
[Host] : .NET 8.0.19 (8.0.1925.36514), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
7+
DefaultJob : .NET 8.0.19 (8.0.1925.36514), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
8+
9+
10+
```
11+
| Method | Mean | Error | StdDev | Allocated |
12+
|----------------------------------- |---------:|---------:|---------:|----------:|
13+
| Space_Publish_Parallel_Inline | 31.31 ns | 0.137 ns | 0.128 ns | - |
14+
| Space_Publish_Parallel_TaskWhenAll | 32.30 ns | 0.104 ns | 0.086 ns | - |

tests/Space.Benchmarks/Handler/HandlerOnlyBench.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
[MemoryDiagnoser]
1717
public class HandlerOnlyBench
1818
{
19-
private ISpace _space = default!;
20-
private Mediator.IMediator _mediator = default!;
21-
private MediatR.IMediator _mediatR = default!;
19+
private ISpace space = default!;
20+
private Mediator.IMediator mediator = default!;
21+
private MediatR.IMediator mediatR = default!;
2222

2323
private static readonly HO_SpaceRequest SpaceReq = new(42);
2424
private static readonly HO_MediatorRequest MediatorReq = new(42);
@@ -31,40 +31,40 @@ public void Setup()
3131
var spServices = new ServiceCollection();
3232
spServices.AddSpace(opt => opt.ServiceLifetime = ServiceLifetime.Singleton);
3333
var spProvider = spServices.BuildServiceProvider();
34-
_space = spProvider.GetRequiredService<ISpace>();
34+
space = spProvider.GetRequiredService<ISpace>();
3535

3636
// Mediator (martinothamar/Mediator)
3737
var medServices = new ServiceCollection();
3838
medServices.AddMediator(opt => opt.ServiceLifetime = ServiceLifetime.Singleton);
3939
var medProvider = medServices.BuildServiceProvider();
40-
_mediator = medProvider.GetRequiredService<Mediator.IMediator>();
40+
mediator = medProvider.GetRequiredService<Mediator.IMediator>();
4141

4242
// MediatR (jbogard/MediatR)
4343
var mrServices = new ServiceCollection();
4444
mrServices.AddMediatR(Assembly.GetExecutingAssembly());
4545
var mrProvider = mrServices.BuildServiceProvider();
46-
_mediatR = mrProvider.GetRequiredService<MediatR.IMediator>();
46+
mediatR = mrProvider.GetRequiredService<MediatR.IMediator>();
4747

4848
// Warm-up
4949
for (int i = 0; i < 10_000; i++)
5050
{
51-
_ = _space.Send<HO_SpaceRequest, HO_Response>(SpaceReq).GetAwaiter().GetResult();
52-
_ = _mediator.Send(MediatorReq).GetAwaiter().GetResult();
53-
_ = _mediatR.Send(MediatRReq).GetAwaiter().GetResult();
51+
_ = space.Send<HO_SpaceRequest, HO_Response>(SpaceReq).GetAwaiter().GetResult();
52+
_ = mediator.Send(MediatorReq).GetAwaiter().GetResult();
53+
_ = mediatR.Send(MediatRReq).GetAwaiter().GetResult();
5454
}
5555
}
5656

5757
[Benchmark]
58-
public ValueTask<HO_Response> Space_Send()
59-
=> _space.Send<HO_SpaceRequest, HO_Response>(SpaceReq);
58+
public async ValueTask<HO_Response> Space_Send()
59+
=> await space.Send<HO_SpaceRequest, HO_Response>(SpaceReq);
6060

6161
[Benchmark]
62-
public Task<HO_Response> Mediator_Send()
63-
=> _mediator.Send(MediatorReq).AsTask();
62+
public async ValueTask<HO_Response> Mediator_Send()
63+
=> await mediator.Send(MediatorReq);
6464

6565
[Benchmark]
66-
public Task<HO_Response> MediatR_Send()
67-
=> _mediatR.Send(MediatRReq);
66+
public async Task<HO_Response> MediatR_Send()
67+
=> await mediatR.Send(MediatRReq);
6868
}
6969

7070
// Space handler

tests/Space.Benchmarks/Notification/NotificationsParallelBench.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ public void Setup()
5757
}
5858

5959
[Benchmark]
60-
public ValueTask Space_Publish_Parallel_Inline()
61-
=> spaceInline.Publish(Event, NotificationDispatchType.Parallel);
60+
public async ValueTask Space_Publish_Parallel_Inline()
61+
=> await spaceInline.Publish(Event, NotificationDispatchType.Parallel);
6262

6363
[Benchmark]
64-
public ValueTask Space_Publish_Parallel_TaskWhenAll()
65-
=> spaceWhenAll.Publish(Event);
64+
public async ValueTask Space_Publish_Parallel_TaskWhenAll()
65+
=> await spaceWhenAll.Publish(Event);
6666
}
6767

6868
// Custom dispatcher that mimics the classic Task.WhenAll fan-out for comparison purposes.

tests/Space.Benchmarks/Notification/NotificationsSequentialBench.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@ public void Setup()
5858
}
5959

6060
[Benchmark]
61-
public ValueTask Space_Publish()
62-
=> space.Publish(Event);
61+
public async ValueTask Space_Publish()
62+
=> await space.Publish(Event);
6363

6464
[Benchmark]
65-
public ValueTask Mediator_Publish()
66-
=> mediatorPublisher.Publish(Event, CancellationToken.None);
65+
public async ValueTask Mediator_Publish()
66+
=> await mediatorPublisher.Publish(Event, CancellationToken.None);
6767

6868
[Benchmark]
69-
public Task MediatR_Publish()
70-
=> mediatR.Publish(Event);
69+
public async Task MediatR_Publish()
70+
=> await mediatR.Publish(Event);
7171
}
7272

7373
// Space notifications (two subscribers)

tests/Space.Benchmarks/Pipeline/HandlerWithPipelineBench.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
[MemoryDiagnoser]
1717
public class HandlerWithPipelineBench
1818
{
19-
private ISpace _space = default!;
20-
private Mediator.IMediator _mediator = default!;
19+
private ISpace space = default!;
20+
private Mediator.IMediator mediator = default!;
2121
private MediatR.IMediator mediatR = default!;
2222

2323
private static readonly HP_SpaceRequest SpaceReq = new(7);
@@ -31,14 +31,14 @@ public void Setup()
3131
var spServices = new ServiceCollection();
3232
spServices.AddSpace(opt => opt.ServiceLifetime = ServiceLifetime.Singleton);
3333
var spProvider = spServices.BuildServiceProvider();
34-
_space = spProvider.GetRequiredService<ISpace>();
34+
space = spProvider.GetRequiredService<ISpace>();
3535

3636
// Mediator + explicit behavior registration for concrete request/response
3737
var medServices = new ServiceCollection();
3838
medServices.AddMediator(opt => opt.ServiceLifetime = ServiceLifetime.Singleton);
3939
medServices.AddSingleton(typeof(Mediator.IPipelineBehavior<HP_MediatorRequest, HP_Response>), typeof(HP_MediatorBehavior));
4040
var medProvider = medServices.BuildServiceProvider();
41-
_mediator = medProvider.GetRequiredService<Mediator.IMediator>();
41+
mediator = medProvider.GetRequiredService<Mediator.IMediator>();
4242

4343
// MediatR + explicit behavior registration for concrete request/response
4444
var mrServices = new ServiceCollection();
@@ -50,23 +50,23 @@ public void Setup()
5050
// Warm-up
5151
for (int i = 0; i < 10_000; i++)
5252
{
53-
_ = _space.Send<HP_SpaceRequest, HP_Response>(SpaceReq).GetAwaiter().GetResult();
54-
_ = _mediator.Send(MediatorReq).GetAwaiter().GetResult();
55-
//_ = _mediatR.Send(MediatRReq).GetAwaiter().GetResult();
53+
_ = space.Send<HP_SpaceRequest, HP_Response>(SpaceReq).GetAwaiter().GetResult();
54+
_ = mediator.Send(MediatorReq).GetAwaiter().GetResult();
55+
_ = mediatR.Send(MediatRReq).GetAwaiter().GetResult();
5656
}
5757
}
5858

5959
[Benchmark]
60-
public ValueTask<HP_Response> Space_Send_WithPipeline()
61-
=> _space.Send<HP_SpaceRequest, HP_Response>(SpaceReq);
60+
public async ValueTask<HP_Response> Space_Send_WithPipeline()
61+
=> await space.Send<HP_SpaceRequest, HP_Response>(SpaceReq);
6262

6363
[Benchmark]
64-
public ValueTask<HP_Response> Mediator_Send_WithBehavior()
65-
=> _mediator.Send(MediatorReq);
64+
public async ValueTask<HP_Response> Mediator_Send_WithBehavior()
65+
=> await mediator.Send(MediatorReq);
6666

67-
//[Benchmark]
68-
public Task<HP_Response> MediatR_Send_WithBehavior()
69-
=> mediatR.Send(MediatRReq);
67+
[Benchmark]
68+
public async Task<HP_Response> MediatR_Send_WithBehavior()
69+
=> await mediatR.Send(MediatRReq);
7070
}
7171

7272
// Space: handler + pipeline

0 commit comments

Comments
 (0)