mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-13 22:25:37 +08:00
fix(cqrs-benchmarks): 对齐 request lifetime 宿主路径
- 新增 request lifetime benchmark 的 generated registry,提供最小 generated request descriptor。 - 更新 RequestLifetimeBenchmarks 使用 generated-provider 宿主,并保留 Singleton/Transient 生命周期矩阵控制。 - 补充 dispatcher 缓存清理,避免生命周期矩阵之间互相污染 benchmark 结果。
This commit is contained in:
parent
f9dd105bcc
commit
f9c9561f40
@ -0,0 +1,112 @@
|
|||||||
|
// Copyright (c) 2025-2026 GeWuYou
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GFramework.Core.Abstractions.Logging;
|
||||||
|
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
[assembly: GFramework.Cqrs.CqrsHandlerRegistryAttribute(
|
||||||
|
typeof(GFramework.Cqrs.Benchmarks.Messaging.GeneratedRequestLifetimeBenchmarkRegistry))]
|
||||||
|
|
||||||
|
namespace GFramework.Cqrs.Benchmarks.Messaging;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 为 request 生命周期矩阵 benchmark 提供 hand-written generated registry,
|
||||||
|
/// 以便在默认 generated-provider 宿主路径上比较不同 handler 生命周期的 dispatch 成本。
|
||||||
|
/// </summary>
|
||||||
|
public sealed class GeneratedRequestLifetimeBenchmarkRegistry :
|
||||||
|
GFramework.Cqrs.ICqrsHandlerRegistry,
|
||||||
|
GFramework.Cqrs.ICqrsRequestInvokerProvider,
|
||||||
|
GFramework.Cqrs.IEnumeratesCqrsRequestInvokerDescriptors
|
||||||
|
{
|
||||||
|
private static readonly GFramework.Cqrs.CqrsRequestInvokerDescriptor Descriptor =
|
||||||
|
new(
|
||||||
|
typeof(IRequestHandler<
|
||||||
|
RequestLifetimeBenchmarks.BenchmarkRequest,
|
||||||
|
RequestLifetimeBenchmarks.BenchmarkResponse>),
|
||||||
|
typeof(GeneratedRequestLifetimeBenchmarkRegistry).GetMethod(
|
||||||
|
nameof(InvokeBenchmarkRequestHandler),
|
||||||
|
BindingFlags.Public | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("Missing generated request lifetime benchmark method."));
|
||||||
|
|
||||||
|
private static readonly IReadOnlyList<GFramework.Cqrs.CqrsRequestInvokerDescriptorEntry> Descriptors =
|
||||||
|
[
|
||||||
|
new GFramework.Cqrs.CqrsRequestInvokerDescriptorEntry(
|
||||||
|
typeof(RequestLifetimeBenchmarks.BenchmarkRequest),
|
||||||
|
typeof(RequestLifetimeBenchmarks.BenchmarkResponse),
|
||||||
|
Descriptor)
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 参与程序集注册入口,但不在这里直接写入 handler 生命周期。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">当前 generated registry 拥有的服务集合。</param>
|
||||||
|
/// <param name="logger">用于记录 generated registry 注册行为的日志器。</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// 生命周期矩阵需要让 benchmark 主体显式控制 `Singleton / Transient` 变量。
|
||||||
|
/// 因此 registry 只负责暴露 generated descriptor,不在这里抢先注册 handler,避免把默认单例注册混入比较结果。
|
||||||
|
/// </remarks>
|
||||||
|
public void Register(IServiceCollection services, ILogger logger)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(services);
|
||||||
|
ArgumentNullException.ThrowIfNull(logger);
|
||||||
|
|
||||||
|
logger.Debug("Registered generated request lifetime benchmark descriptors.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 返回当前 provider 暴露的全部 generated request invoker 描述符。
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>当前 benchmark 需要的 request invoker 描述符集合。</returns>
|
||||||
|
public IReadOnlyList<GFramework.Cqrs.CqrsRequestInvokerDescriptorEntry> GetDescriptors()
|
||||||
|
{
|
||||||
|
return Descriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 为目标请求/响应类型对返回 generated request invoker 描述符。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="requestType">待匹配的请求类型。</param>
|
||||||
|
/// <param name="responseType">待匹配的响应类型。</param>
|
||||||
|
/// <param name="descriptor">命中时返回的 generated descriptor。</param>
|
||||||
|
/// <returns>命中当前 benchmark 的请求/响应类型对时返回 <see langword="true" />。</returns>
|
||||||
|
public bool TryGetDescriptor(
|
||||||
|
Type requestType,
|
||||||
|
Type responseType,
|
||||||
|
out GFramework.Cqrs.CqrsRequestInvokerDescriptor? descriptor)
|
||||||
|
{
|
||||||
|
if (requestType == typeof(RequestLifetimeBenchmarks.BenchmarkRequest) &&
|
||||||
|
responseType == typeof(RequestLifetimeBenchmarks.BenchmarkResponse))
|
||||||
|
{
|
||||||
|
descriptor = Descriptor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模拟 generated request invoker provider 为生命周期矩阵 benchmark 产出的开放静态调用入口。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handler">当前请求对应的 handler 实例。</param>
|
||||||
|
/// <param name="request">待分发的 request。</param>
|
||||||
|
/// <param name="cancellationToken">调用方传入的取消令牌。</param>
|
||||||
|
/// <returns>交给目标 request handler 处理后的响应任务。</returns>
|
||||||
|
public static ValueTask<RequestLifetimeBenchmarks.BenchmarkResponse> InvokeBenchmarkRequestHandler(
|
||||||
|
object handler,
|
||||||
|
object request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var typedHandler = (IRequestHandler<
|
||||||
|
RequestLifetimeBenchmarks.BenchmarkRequest,
|
||||||
|
RequestLifetimeBenchmarks.BenchmarkResponse>)handler;
|
||||||
|
var typedRequest = (RequestLifetimeBenchmarks.BenchmarkRequest)request;
|
||||||
|
return typedHandler.Handle(typedRequest, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -85,14 +85,18 @@ public class RequestLifetimeBenchmarks
|
|||||||
MinLevel = LogLevel.Fatal
|
MinLevel = LogLevel.Fatal
|
||||||
};
|
};
|
||||||
Fixture.Setup($"RequestLifetime/{Lifetime}", handlerCount: 1, pipelineCount: 0);
|
Fixture.Setup($"RequestLifetime/{Lifetime}", handlerCount: 1, pipelineCount: 0);
|
||||||
|
BenchmarkDispatcherCacheHelper.ClearDispatcherCaches();
|
||||||
|
|
||||||
_baselineHandler = new BenchmarkRequestHandler();
|
_baselineHandler = new BenchmarkRequestHandler();
|
||||||
_request = new BenchmarkRequest(Guid.NewGuid());
|
_request = new BenchmarkRequest(Guid.NewGuid());
|
||||||
|
|
||||||
_container = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
_container = BenchmarkHostFactory.CreateFrozenGFrameworkContainer(container =>
|
||||||
{
|
{
|
||||||
|
BenchmarkHostFactory.RegisterGeneratedBenchmarkRegistry<GeneratedRequestLifetimeBenchmarkRegistry>(container);
|
||||||
RegisterGFrameworkHandler(container, Lifetime);
|
RegisterGFrameworkHandler(container, Lifetime);
|
||||||
});
|
});
|
||||||
|
// 容器内已提前保留默认 runtime 以支撑 generated registry 接线;
|
||||||
|
// 这里额外创建带生命周期后缀的 runtime,只是为了区分不同 benchmark 矩阵的 dispatcher 日志。
|
||||||
_runtime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(
|
_runtime = GFramework.Cqrs.CqrsRuntimeFactory.CreateRuntime(
|
||||||
_container,
|
_container,
|
||||||
LoggerFactoryResolver.Provider.CreateLogger(nameof(RequestLifetimeBenchmarks) + "." + Lifetime));
|
LoggerFactoryResolver.Provider.CreateLogger(nameof(RequestLifetimeBenchmarks) + "." + Lifetime));
|
||||||
@ -111,7 +115,14 @@ public class RequestLifetimeBenchmarks
|
|||||||
[GlobalCleanup]
|
[GlobalCleanup]
|
||||||
public void Cleanup()
|
public void Cleanup()
|
||||||
{
|
{
|
||||||
BenchmarkCleanupHelper.DisposeAll(_container, _serviceProvider);
|
try
|
||||||
|
{
|
||||||
|
BenchmarkCleanupHelper.DisposeAll(_container, _serviceProvider);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
BenchmarkDispatcherCacheHelper.ClearDispatcherCaches();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -146,6 +157,10 @@ public class RequestLifetimeBenchmarks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="container">当前 benchmark 拥有并负责释放的容器。</param>
|
/// <param name="container">当前 benchmark 拥有并负责释放的容器。</param>
|
||||||
/// <param name="lifetime">待比较的 handler 生命周期。</param>
|
/// <param name="lifetime">待比较的 handler 生命周期。</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// 先通过 generated registry 提供静态 descriptor,再显式覆盖 handler 生命周期,
|
||||||
|
/// 可以把比较变量收敛到 handler 解析成本,而不是 descriptor 发现路径本身。
|
||||||
|
/// </remarks>
|
||||||
private static void RegisterGFrameworkHandler(MicrosoftDiContainer container, HandlerLifetime lifetime)
|
private static void RegisterGFrameworkHandler(MicrosoftDiContainer container, HandlerLifetime lifetime)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(container);
|
ArgumentNullException.ThrowIfNull(container);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user