Skip to content

Commit d6a7ae3

Browse files
committed
Add wolverine as a comparison library
1 parent a2fc6cb commit d6a7ae3

5 files changed

Lines changed: 102 additions & 3 deletions

File tree

.github/scripts/Update-BenchmarkDocs.ps1

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ $groups = @{
6868
}
6969

7070
# Define the order of implementations
71-
$implOrder = @('Direct', 'Foundatio', 'MediatR', 'MassTransit')
71+
$implOrder = @('Direct', 'Foundatio', 'MediatR', 'Wolverine', 'MassTransit')
7272

7373
foreach ($row in $csv) {
7474
$method = $row.Method
@@ -84,7 +84,8 @@ foreach ($row in $csv) {
8484
}
8585

8686
# Sort each group by implementation order
87-
foreach ($key in $groups.Keys) {
87+
$groupKeys = @($groups.Keys)
88+
foreach ($key in $groupKeys) {
8889
$groups[$key] = $groups[$key] | Sort-Object {
8990
$method = $_.Method
9091
for ($i = 0; $i -lt $implOrder.Count; $i++) {

.github/workflows/benchmarks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
5353
git add docs/guide/performance.md
5454
git commit -m "📊 Update benchmark results [skip ci]"
55-
55+
5656
# Pull with rebase in case changes were pushed while benchmarks ran
5757
git pull --rebase origin main
5858
git push

benchmarks/Foundatio.Mediator.Benchmarks/CoreBenchmarks.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
using Foundatio.Mediator.Benchmarks.Handlers.Foundatio;
44
using Foundatio.Mediator.Benchmarks.Services;
55
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.Hosting;
7+
using Microsoft.Extensions.Logging;
68
using MassTransit;
9+
using Wolverine;
710

811
namespace Foundatio.Mediator.Benchmarks;
912

@@ -14,9 +17,11 @@ public class CoreBenchmarks
1417
private IServiceProvider _foundatioServices = null!;
1518
private IServiceProvider _mediatrServices = null!;
1619
private IServiceProvider _masstransitServices = null!;
20+
private IHost _wolverineHost = null!;
1721
private Foundatio.Mediator.IMediator _foundatioMediator = null!;
1822
private MediatR.IMediator _mediatrMediator = null!;
1923
private MassTransit.Mediator.IMediator _masstransitMediator = null!;
24+
private IMessageBus _wolverineBus = null!;
2025

2126
// Direct handler instances for baseline comparison
2227
private readonly FoundatioCommandHandler _directCommandHandler = new();
@@ -65,6 +70,18 @@ public void Setup()
6570
});
6671
_masstransitServices = masstransitServices.BuildServiceProvider();
6772
_masstransitMediator = _masstransitServices.GetRequiredService<MassTransit.Mediator.IMediator>();
73+
74+
// Setup Wolverine
75+
_wolverineHost = Host.CreateDefaultBuilder()
76+
.ConfigureLogging(logging => logging.ClearProviders())
77+
.UseWolverine(opts =>
78+
{
79+
opts.Services.AddSingleton<IOrderService, OrderService>();
80+
opts.Discovery.IncludeAssembly(typeof(CoreBenchmarks).Assembly);
81+
})
82+
.Build();
83+
_wolverineHost.Start();
84+
_wolverineBus = _wolverineHost.Services.GetRequiredService<IMessageBus>();
6885
}
6986

7087
[GlobalCleanup]
@@ -77,6 +94,9 @@ public async Task Cleanup()
7794
await asyncDisposable.DisposeAsync();
7895
else
7996
(_masstransitServices as IDisposable)?.Dispose();
97+
98+
await _wolverineHost.StopAsync();
99+
_wolverineHost.Dispose();
80100
}
81101

82102
// Baseline: Direct method calls (no mediator overhead)
@@ -123,6 +143,12 @@ public async Task MassTransit_Command()
123143
await _masstransitMediator.Send(_pingCommand);
124144
}
125145

146+
[Benchmark]
147+
public async Task Wolverine_Command()
148+
{
149+
await _wolverineBus.InvokeAsync(_pingCommand);
150+
}
151+
126152
// Scenario 2: InvokeAsync<T> (Query)
127153
[Benchmark]
128154
public async Task<Order> Foundatio_Query()
@@ -144,6 +170,12 @@ public async Task<Order> MassTransit_Query()
144170
return response.Message;
145171
}
146172

173+
[Benchmark]
174+
public async Task<Order?> Wolverine_Query()
175+
{
176+
return await _wolverineBus.InvokeAsync<Order>(_getOrder);
177+
}
178+
147179
// Scenario 3: PublishAsync with a single handler
148180
[Benchmark]
149181
public async Task Foundatio_Publish()
@@ -163,6 +195,12 @@ public async Task MassTransit_Publish()
163195
await _masstransitMediator.Publish(_userRegisteredEvent);
164196
}
165197

198+
[Benchmark]
199+
public async Task Wolverine_Publish()
200+
{
201+
await _wolverineBus.PublishAsync(_userRegisteredEvent);
202+
}
203+
166204
// Scenario 4: InvokeAsync<T> with DI (Query with dependency injection)
167205
[Benchmark]
168206
public async Task<Order> Foundatio_QueryWithDependencies()
@@ -183,4 +221,10 @@ public async Task<Order> MassTransit_QueryWithDependencies()
183221
var response = await client.GetResponse<Order>(_getOrderWithDependencies);
184222
return response.Message;
185223
}
224+
225+
[Benchmark]
226+
public async Task<Order?> Wolverine_QueryWithDependencies()
227+
{
228+
return await _wolverineBus.InvokeAsync<Order>(_getOrderWithDependencies);
229+
}
186230
}

benchmarks/Foundatio.Mediator.Benchmarks/Foundatio.Mediator.Benchmarks.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
<Nullable>enable</Nullable>
88
<IsPackable>false</IsPackable>
99
<PublishAot>false</PublishAot>
10+
<!-- Suppress NuGet warnings for version constraint overrides (Wolverine doesn't support .NET 10 yet) -->
11+
<NoWarn>$(NoWarn);NU1608;NU1603</NoWarn>
1012
<!-- Emit compiler generated files for debugging purposes -->
1113
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
1214
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
@@ -39,8 +41,14 @@
3941
<PackageReference Include="BenchmarkDotNet" Version="0.15.8" />
4042
<PackageReference Include="MassTransit" Version="8.5.7" />
4143
<PackageReference Include="MediatR" Version="12.4.1" />
44+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.0" />
45+
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0" />
4246
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
47+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
48+
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.0" />
49+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
4350
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.0" />
51+
<PackageReference Include="WolverineFx" Version="3.9.0" />
4452
</ItemGroup>
4553

4654
</Project>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Foundatio.Mediator.Benchmarks.Messages;
2+
using Foundatio.Mediator.Benchmarks.Services;
3+
4+
namespace Foundatio.Mediator.Benchmarks.Handlers.Wolverine;
5+
6+
// Scenario 1: Command handler (InvokeAsync without response)
7+
[FoundatioIgnore]
8+
public class WolverineCommandHandler
9+
{
10+
public Task Handle(PingCommand command)
11+
{
12+
// Simulate minimal work
13+
return Task.CompletedTask;
14+
}
15+
}
16+
17+
// Scenario 2: Query handler (InvokeAsync<T>) - No DI for baseline comparison
18+
[FoundatioIgnore]
19+
public class WolverineQueryHandler
20+
{
21+
public Task<Order> Handle(GetOrder query)
22+
{
23+
return Task.FromResult(new Order(query.Id, 99.99m, DateTime.UtcNow));
24+
}
25+
}
26+
27+
// Scenario 3: Single event handler (PublishAsync with single handler)
28+
[FoundatioIgnore]
29+
public class WolverineEventHandler
30+
{
31+
public Task Handle(UserRegisteredEvent notification)
32+
{
33+
// Simulate minimal event handling work
34+
return Task.CompletedTask;
35+
}
36+
}
37+
38+
// Scenario 4: Query handler with dependency injection
39+
[FoundatioIgnore]
40+
public class WolverineQueryWithDependenciesHandler
41+
{
42+
public Task<Order> Handle(GetOrderWithDependencies query, IOrderService orderService)
43+
{
44+
return orderService.GetOrderAsync(query.Id);
45+
}
46+
}

0 commit comments

Comments
 (0)