test(cqrs-benchmarks): 补齐 stream steady-state Mediator 对照

- 新增 StreamingBenchmarks 中的 Mediator steady-state stream 对照与对应 handler 契约。

- 更新 benchmark README 的 stream coverage 与 gap 描述,使其与当前实现一致。
This commit is contained in:
gewuyou 2026-05-12 08:47:25 +08:00 committed by GeWuYou
parent 4cc7060fcf
commit 40efb4f763
2 changed files with 36 additions and 9 deletions

View File

@ -17,6 +17,7 @@ using GFramework.Core.Logging;
using GFramework.Cqrs.Abstractions.Cqrs;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using GeneratedMediator = Mediator.Mediator;
[assembly: GFramework.Cqrs.CqrsHandlerRegistryAttribute(
typeof(GFramework.Cqrs.Benchmarks.Messaging.GeneratedDefaultStreamingBenchmarkRegistry))]
@ -24,7 +25,7 @@ using Microsoft.Extensions.DependencyInjection;
namespace GFramework.Cqrs.Benchmarks.Messaging;
/// <summary>
/// 对比单个 stream request 在直接调用、GFramework.CQRS runtime 与 MediatR 之间的 steady-state stream 开销。
/// 对比单个 stream request 在直接调用、GFramework.CQRS runtime、NuGet `Mediator` 与 MediatR 之间的 steady-state stream 开销。
/// </summary>
/// <remarks>
/// 默认 generated-provider stream 宿主同时暴露 <see cref="StreamObservation.FirstItem" /> 与
@ -36,8 +37,10 @@ public class StreamingBenchmarks
{
private MicrosoftDiContainer _container = null!;
private ICqrsRuntime _runtime = null!;
private ServiceProvider _serviceProvider = null!;
private ServiceProvider _mediatrServiceProvider = null!;
private ServiceProvider _mediatorServiceProvider = null!;
private IMediator _mediatr = null!;
private GeneratedMediator _mediator = null!;
private BenchmarkStreamHandler _baselineHandler = null!;
private BenchmarkStreamRequest _request = null!;
@ -100,25 +103,28 @@ public class StreamingBenchmarks
_container,
LoggerFactoryResolver.Provider.CreateLogger(nameof(StreamingBenchmarks)));
_serviceProvider = BenchmarkHostFactory.CreateMediatRServiceProvider(
_mediatrServiceProvider = BenchmarkHostFactory.CreateMediatRServiceProvider(
configure: null,
typeof(StreamingBenchmarks),
static candidateType => candidateType == typeof(BenchmarkStreamHandler),
ServiceLifetime.Singleton);
_mediatr = _serviceProvider.GetRequiredService<IMediator>();
_mediatr = _mediatrServiceProvider.GetRequiredService<IMediator>();
_mediatorServiceProvider = BenchmarkHostFactory.CreateMediatorServiceProvider(configure: null);
_mediator = _mediatorServiceProvider.GetRequiredService<GeneratedMediator>();
_request = new BenchmarkStreamRequest(Guid.NewGuid(), 3);
}
/// <summary>
/// 释放 MediatR 对照组使用的 DI 宿主。
/// 释放 MediatR 与 `Mediator` 对照组使用的 DI 宿主。
/// </summary>
[GlobalCleanup]
public void Cleanup()
{
try
{
BenchmarkCleanupHelper.DisposeAll(_container, _serviceProvider);
BenchmarkCleanupHelper.DisposeAll(_container, _mediatrServiceProvider, _mediatorServiceProvider);
}
finally
{
@ -158,6 +164,15 @@ public class StreamingBenchmarks
return ObserveAsync(_mediatr.CreateStream(_request, CancellationToken.None), Observation);
}
/// <summary>
/// 通过 `ai-libs/Mediator` 的 source-generated concrete mediator 创建 stream并按当前观测模式消费。
/// </summary>
[Benchmark]
public ValueTask Stream_Mediator()
{
return ObserveAsync(_mediator.CreateStream(_request, CancellationToken.None), Observation);
}
/// <summary>
/// 按观测模式消费 stream便于把“建流/首个元素”和“完整枚举”分开观察。
/// </summary>
@ -224,6 +239,7 @@ public class StreamingBenchmarks
/// <param name="ItemCount">返回元素数量。</param>
public sealed record BenchmarkStreamRequest(Guid Id, int ItemCount) :
GFramework.Cqrs.Abstractions.Cqrs.IStreamRequest<BenchmarkResponse>,
Mediator.IStreamRequest<BenchmarkResponse>,
MediatR.IStreamRequest<BenchmarkResponse>;
/// <summary>
@ -233,10 +249,11 @@ public class StreamingBenchmarks
public sealed record BenchmarkResponse(Guid Id);
/// <summary>
/// 同时实现 GFramework.CQRS 与 MediatR 契约的最小 stream handler。
/// 同时实现 GFramework.CQRS、NuGet `Mediator` 与 MediatR 契约的最小 stream handler。
/// </summary>
public sealed class BenchmarkStreamHandler :
GFramework.Cqrs.Abstractions.Cqrs.IStreamRequestHandler<BenchmarkStreamRequest, BenchmarkResponse>,
Mediator.IStreamRequestHandler<BenchmarkStreamRequest, BenchmarkResponse>,
MediatR.IStreamRequestHandler<BenchmarkStreamRequest, BenchmarkResponse>
{
/// <summary>
@ -249,6 +266,16 @@ public class StreamingBenchmarks
return EnumerateAsync(request, cancellationToken);
}
/// <summary>
/// 处理 NuGet `Mediator` stream request。
/// </summary>
IAsyncEnumerable<BenchmarkResponse> Mediator.IStreamRequestHandler<BenchmarkStreamRequest, BenchmarkResponse>.Handle(
BenchmarkStreamRequest request,
CancellationToken cancellationToken)
{
return Handle(request, cancellationToken);
}
/// <summary>
/// 处理 MediatR stream request。
/// </summary>

View File

@ -26,7 +26,7 @@
- `Initialization``ColdStart` 两组下,`GFramework.Cqrs`、NuGet `Mediator``MediatR`
- stream steady-state
- `Messaging/StreamingBenchmarks.cs`
- baseline、默认 generated-provider 宿主接线的 `GFramework.Cqrs` runtime 与 `MediatR`
- baseline、默认 generated-provider 宿主接线的 `GFramework.Cqrs` runtime、NuGet `Mediator` source-generated concrete path`MediatR`
- 同时提供 `FirstItem``DrainAll` 两种观测口径
- `Messaging/StreamLifetimeBenchmarks.cs`
- `Singleton / Scoped / Transient` 三类 handler 生命周期下baseline、`GFramework.Cqrs` reflection stream binding、`GFramework.Cqrs` generated stream registry、`MediatR`
@ -100,6 +100,6 @@ dotnet run --project GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.cspro
## 当前缺口
- 当前没有 stream 版的 NuGet `Mediator` source-generated concrete path 对照;stream steady-state、lifetime、startup 现在都只覆盖 `GFramework.Cqrs``MediatR`
- 当前没有 stream 生命周期与 startup 版的 NuGet `Mediator` source-generated concrete path 对照;`StreamLifetimeBenchmarks``StreamStartupBenchmarks` 现在都只覆盖 `GFramework.Cqrs``MediatR`
- 当前没有 request 生命周期下的 NuGet `Mediator` compile-time lifetime 矩阵;`RequestLifetimeBenchmarks` 只覆盖 `GFramework.Cqrs``MediatR`
- 当前没有 notification fan-out 的生命周期矩阵;`NotificationFanOutBenchmarks` 只覆盖固定 `4 handler` 的已装配宿主