Skip to content

Commit 5b3b899

Browse files
committed
Updating some benchmark code
1 parent c465e5b commit 5b3b899

File tree

4 files changed

+28
-25
lines changed

4 files changed

+28
-25
lines changed

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -294,26 +294,26 @@ We chose `IDispatcher` and `Dispatcher` because the name honestly describes the
294294

295295
There are many great request dispatcher / "mediator" implementations out there. Here is a comparison between ResultR and some of the other popular ones:
296296

297-
Performance comparison between ResultR (latest), [MediatR](https://github.com/jbogard/MediatR) (12.5.0), [DispatchR](https://github.com/hasanxdev/DispatchR) (2.1.1), and [Mediator.SourceGenerator](https://github.com/martinothamar/Mediator) (2.1.7):
297+
Performance comparison between ResultR (latest), [MediatR](https://github.com/jbogard/MediatR) (12.5.0), [DispatchR](https://github.com/hasanxdev/DispatchR) (2.1.1), and [Mediator.SourceGenerator](https://github.com/martinothamar/Mediator) (3.0.1):
298298

299299
| Method | Mean | Allocated | Ratio |
300300
|------------------------------ |----------:|----------:|------:|
301-
| MediatorSG - With Validation | 20.26 ns | 72 B | 0.27 |
302-
| MediatorSG - Simple | 23.01 ns | 72 B | 0.31 |
303-
| DispatchR - With Validation | 31.37 ns | 96 B | 0.42 |
304-
| DispatchR - Simple | 34.93 ns | 96 B | 0.47 |
305-
| DispatchR - Full Pipeline | 44.02 ns | 96 B | 0.59 |
306-
| MediatorSG - Full Pipeline | 44.35 ns | 72 B | 0.59 |
307-
| ResultR - Full Pipeline | 62.92 ns | 264 B | 0.84 |
308-
| MediatR - Simple | 75.03 ns | 296 B | 1.00 |
309-
| ResultR - With Validation | 77.10 ns | 264 B | 1.03 |
310-
| ResultR - Simple | 95.42 ns | 264 B | 1.27 |
311-
| MediatR - With Validation | 120.28 ns | 608 B | 1.60 |
312-
| MediatR - Full Pipeline | 158.01 ns | 824 B | 2.11 |
301+
| MediatorSG - Simple | 17.15 ns | 72 B | 0.25 |
302+
| MediatorSG - With Validation | 21.46 ns | 72 B | 0.31 |
303+
| DispatchR - With Validation | 38.51 ns | 96 B | 0.56 |
304+
| DispatchR - Simple | 39.33 ns | 96 B | 0.58 |
305+
| MediatorSG - Full Pipeline | 44.27 ns | 72 B | 0.65 |
306+
| DispatchR - Full Pipeline | 65.27 ns | 96 B | 0.96 |
307+
| MediatR - Simple | 68.23 ns | 296 B | 1.00 |
308+
| ResultR - Full Pipeline | 73.34 ns | 264 B | 1.08 |
309+
| ResultR - With Validation | 75.46 ns | 264 B | 1.11 |
310+
| ResultR - Simple | 80.65 ns | 264 B | 1.18 |
311+
| MediatR - With Validation | 139.48 ns | 608 B | 2.05 |
312+
| MediatR - Full Pipeline | 169.90 ns | 824 B | 2.49 |
313313

314314
> **Note on benchmark methodology:** All libraries are configured with equivalent pipeline behaviors (validation, pre/post processing) for fair comparison. MediatorSG and DispatchR use source generation for optimal performance. ResultR always executes its full pipeline (Validate → BeforeHandle → Handle → AfterHandle) even when hooks use default implementations, which explains why "Simple" is slower than "Full Pipeline" - they're doing the same work.
315315
316-
> **What does this mean?** When comparing equivalent functionality (full pipeline with behaviors), ResultR (63ns) significantly outperforms MediatR (158ns) - over 2.5x faster. The source-generated libraries (MediatorSG, DispatchR) are fastest but require compile-time code generation. In real applications where database queries take 1-10ms and HTTP calls take 50-500ms, these nanosecond differences are negligible. ResultR also allocates less memory than MediatR (264B vs 296-824B), reducing GC pressure in high-throughput scenarios.
316+
> **What does this mean?** When comparing equivalent functionality (full pipeline with behaviors), ResultR (73ns) significantly outperforms MediatR (170ns) - over 2.3x faster. The source-generated libraries (MediatorSG, DispatchR) are fastest but require compile-time code generation. In real applications where database queries take 1-10ms and HTTP calls take 50-500ms, these nanosecond differences are negligible. ResultR also allocates less memory than MediatR (264B vs 296-824B), reducing GC pressure in high-throughput scenarios.
317317
318318
Run benchmarks locally:
319319
```bash

src/ResultR.Benchmarks/DispatcherBenchmarks.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,13 @@ public void Setup()
5757
_dispatchRProvider = dispatchRServices.BuildServiceProvider();
5858
_dispatchRMediator = _dispatchRProvider.GetRequiredService<global::DispatchR.IMediator>();
5959

60-
// Mediator.SourceGenerator setup - register pipeline behaviors manually for v2.x
60+
// Mediator.SourceGenerator setup - v3.x provides AddMediator extension
6161
var mediatorSGServices = new ServiceCollection();
62-
mediatorSGServices.AddMediator();
63-
// Register specific pipeline behaviors (v2.x doesn't have MediatorOptions.PipelineBehaviors)
62+
mediatorSGServices.AddMediator(options =>
63+
{
64+
options.ServiceLifetime = ServiceLifetime.Singleton;
65+
});
66+
// Register pipeline behaviors manually
6467
mediatorSGServices.AddSingleton<global::Mediator.IPipelineBehavior<MediatorSGValidatedRequest, int>, MediatorSGValidationBehavior>();
6568
mediatorSGServices.AddSingleton<global::Mediator.IPipelineBehavior<MediatorSGFullPipelineRequest, int>, MediatorSGPreProcessorBehavior>();
6669
mediatorSGServices.AddSingleton<global::Mediator.IPipelineBehavior<MediatorSGFullPipelineRequest, int>, MediatorSGPostProcessorBehavior>();

src/ResultR.Benchmarks/Requests/MediatorSGRequests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ public sealed class MediatorSGValidationBehavior : MSG.IPipelineBehavior<Mediato
2929
{
3030
public ValueTask<int> Handle(
3131
MediatorSGValidatedRequest message,
32-
CancellationToken cancellationToken,
33-
MSG.MessageHandlerDelegate<MediatorSGValidatedRequest, int> next)
32+
MSG.MessageHandlerDelegate<MediatorSGValidatedRequest, int> next,
33+
CancellationToken cancellationToken)
3434
{
3535
// Simulate validation check
3636
if (message.Value < 0)
@@ -57,8 +57,8 @@ public sealed class MediatorSGPreProcessorBehavior : MSG.IPipelineBehavior<Media
5757
{
5858
public ValueTask<int> Handle(
5959
MediatorSGFullPipelineRequest message,
60-
CancellationToken cancellationToken,
61-
MSG.MessageHandlerDelegate<MediatorSGFullPipelineRequest, int> next)
60+
MSG.MessageHandlerDelegate<MediatorSGFullPipelineRequest, int> next,
61+
CancellationToken cancellationToken)
6262
{
6363
// Pre-process
6464
return next(message, cancellationToken);
@@ -70,8 +70,8 @@ public sealed class MediatorSGPostProcessorBehavior : MSG.IPipelineBehavior<Medi
7070
{
7171
public async ValueTask<int> Handle(
7272
MediatorSGFullPipelineRequest message,
73-
CancellationToken cancellationToken,
74-
MSG.MessageHandlerDelegate<MediatorSGFullPipelineRequest, int> next)
73+
MSG.MessageHandlerDelegate<MediatorSGFullPipelineRequest, int> next,
74+
CancellationToken cancellationToken)
7575
{
7676
var result = await next(message, cancellationToken);
7777
// Post-process

src/ResultR.Benchmarks/ResultR.Benchmarks.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
<PackageReference Include="DispatchR.Mediator" Version="2.1.1" />
1515
<PackageReference Include="MediatR" Version="12.5.0" />
1616
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
17-
<PackageReference Include="Mediator.Abstractions" Version="2.1.7" />
18-
<PackageReference Include="Mediator.SourceGenerator" Version="2.1.7">
17+
<PackageReference Include="Mediator.Abstractions" Version="3.0.1" />
18+
<PackageReference Include="Mediator.SourceGenerator" Version="3.0.1">
1919
<PrivateAssets>all</PrivateAssets>
2020
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
2121
</PackageReference>

0 commit comments

Comments
 (0)