docs(cqrs-benchmarks): 补齐stream与notification基准返回值文档

- 补充 stream 与 notification benchmark 公开方法缺失的 XML returns 契约

- 更新 request startup benchmark 的返回值文档说明

- 同步 cqrs-rewrite 的批处理恢复点与停点决策
This commit is contained in:
gewuyou 2026-05-12 13:36:54 +08:00
parent 555c7c07ac
commit c32a1ec4ae
8 changed files with 113 additions and 7 deletions

View File

@ -95,6 +95,7 @@ public class NotificationBenchmarks
/// <summary>
/// 通过 GFramework.CQRS runtime 发布 notification。
/// </summary>
/// <returns>代表当前 GFramework.CQRS publish 完成的值任务。</returns>
[Benchmark(Baseline = true)]
public ValueTask PublishNotification_GFrameworkCqrs()
{
@ -104,6 +105,7 @@ public class NotificationBenchmarks
/// <summary>
/// 通过 MediatR 发布 notification作为外部设计对照。
/// </summary>
/// <returns>代表当前 MediatR publish 完成的任务。</returns>
[Benchmark]
public Task PublishNotification_MediatR()
{
@ -113,6 +115,7 @@ public class NotificationBenchmarks
/// <summary>
/// 通过 `Mediator` source-generated concrete mediator 发布 notification作为高性能对照组。
/// </summary>
/// <returns>代表当前 `Mediator` publish 完成的值任务。</returns>
[Benchmark]
public ValueTask PublishNotification_Mediator()
{

View File

@ -123,6 +123,7 @@ public class NotificationFanOutBenchmarks
/// <summary>
/// 直接依次调用 4 个处理器,作为 fan-out dispatch 额外开销的 baseline。
/// </summary>
/// <returns>代表基线顺序调用 4 个处理器完成当前 notification 处理的值任务。</returns>
[Benchmark(Baseline = true)]
public async ValueTask PublishNotification_Baseline()
{
@ -135,6 +136,7 @@ public class NotificationFanOutBenchmarks
/// <summary>
/// 通过默认顺序发布器的 GFramework.CQRS runtime 发布固定 4 处理器的 notification。
/// </summary>
/// <returns>代表当前默认顺序发布器 publish 完成的值任务。</returns>
[Benchmark]
public ValueTask PublishNotification_GFrameworkCqrsSequential()
{
@ -144,6 +146,7 @@ public class NotificationFanOutBenchmarks
/// <summary>
/// 通过内置 <c>Task.WhenAll(...)</c> 发布器的 GFramework.CQRS runtime 发布固定 4 处理器的 notification。
/// </summary>
/// <returns>代表当前 <c>Task.WhenAll(...)</c> 发布器 publish 完成的值任务。</returns>
[Benchmark]
public ValueTask PublishNotification_GFrameworkCqrsTaskWhenAll()
{
@ -153,6 +156,7 @@ public class NotificationFanOutBenchmarks
/// <summary>
/// 通过 MediatR 发布固定 4 处理器的 notification作为外部设计对照。
/// </summary>
/// <returns>代表当前 MediatR publish 完成的任务。</returns>
[Benchmark]
public Task PublishNotification_MediatR()
{
@ -162,6 +166,7 @@ public class NotificationFanOutBenchmarks
/// <summary>
/// 通过 `Mediator` source-generated concrete mediator 发布固定 4 处理器的 notification作为高性能对照组。
/// </summary>
/// <returns>代表当前 `Mediator` publish 完成的值任务。</returns>
[Benchmark]
public ValueTask PublishNotification_Mediator()
{

View File

@ -97,6 +97,7 @@ public class RequestStartupBenchmarks
/// <summary>
/// 返回已构建宿主中的 MediatR mediator作为 initialization 组的句柄解析 baseline。
/// </summary>
/// <returns>当前 benchmark 复用的 MediatR mediator。</returns>
[Benchmark(Baseline = true)]
[BenchmarkCategory("Initialization")]
public IMediator Initialization_MediatR()
@ -107,6 +108,7 @@ public class RequestStartupBenchmarks
/// <summary>
/// 返回已构建宿主中的 GFramework.CQRS runtime确保与 MediatR baseline 处于相同初始化阶段。
/// </summary>
/// <returns>当前 benchmark 复用的 GFramework.CQRS runtime。</returns>
[Benchmark]
[BenchmarkCategory("Initialization")]
public ICqrsRuntime Initialization_GFrameworkCqrs()
@ -117,6 +119,7 @@ public class RequestStartupBenchmarks
/// <summary>
/// 返回已构建宿主中的 `Mediator` concrete mediator作为 source-generated 对照组的初始化句柄。
/// </summary>
/// <returns>当前 benchmark 复用的 `Mediator` concrete mediator。</returns>
[Benchmark]
[BenchmarkCategory("Initialization")]
public GeneratedMediator Initialization_Mediator()
@ -127,6 +130,7 @@ public class RequestStartupBenchmarks
/// <summary>
/// 在新宿主上首次发送 request作为 MediatR 的 cold-start baseline。
/// </summary>
/// <returns>当前 request 的响应结果。</returns>
[Benchmark(Baseline = true)]
[BenchmarkCategory("ColdStart")]
public async Task<BenchmarkResponse> ColdStart_MediatR()
@ -139,6 +143,7 @@ public class RequestStartupBenchmarks
/// <summary>
/// 在新 runtime 上首次发送 request量化 GFramework.CQRS 的 first-hit 成本。
/// </summary>
/// <returns>当前 request 的响应结果。</returns>
[Benchmark]
[BenchmarkCategory("ColdStart")]
public async ValueTask<BenchmarkResponse> ColdStart_GFrameworkCqrs()
@ -151,6 +156,7 @@ public class RequestStartupBenchmarks
/// <summary>
/// 在新的 `Mediator` 宿主上首次发送 request量化 source-generated concrete path 的 cold-start 成本。
/// </summary>
/// <returns>当前 request 的响应结果。</returns>
[Benchmark]
[BenchmarkCategory("ColdStart")]
public async ValueTask<BenchmarkResponse> ColdStart_Mediator()

View File

@ -143,6 +143,7 @@ public class StreamInvokerBenchmarks
/// <summary>
/// 直接调用最小 stream handler并按当前观测模式消费 stream作为 dispatch 额外开销 baseline。
/// </summary>
/// <returns>代表基线 stream 按当前观测模式消费完成的值任务。</returns>
[Benchmark(Baseline = true)]
public ValueTask Stream_Baseline()
{
@ -152,6 +153,7 @@ public class StreamInvokerBenchmarks
/// <summary>
/// 通过 GFramework.CQRS 反射 stream binding 路径创建 stream并按当前观测模式消费。
/// </summary>
/// <returns>代表当前 GFramework.CQRS 反射 stream 按观测模式消费完成的值任务。</returns>
[Benchmark]
public ValueTask Stream_GFrameworkReflection()
{
@ -166,6 +168,7 @@ public class StreamInvokerBenchmarks
/// <summary>
/// 通过 generated stream invoker provider 预热后的 GFramework.CQRS runtime 创建 stream并按当前观测模式消费。
/// </summary>
/// <returns>代表当前 GFramework.CQRS generated stream 按观测模式消费完成的值任务。</returns>
[Benchmark]
public ValueTask Stream_GFrameworkGenerated()
{
@ -180,6 +183,7 @@ public class StreamInvokerBenchmarks
/// <summary>
/// 通过 MediatR 创建 stream并按当前观测模式消费作为外部对照。
/// </summary>
/// <returns>代表当前 MediatR stream 按观测模式消费完成的值任务。</returns>
[Benchmark]
public ValueTask Stream_MediatR()
{

View File

@ -148,6 +148,7 @@ public class StreamLifetimeBenchmarks
/// <summary>
/// 直接调用 handler并按当前观测模式消费 stream作为不同生命周期矩阵下的 dispatch 额外开销 baseline。
/// </summary>
/// <returns>代表基线 handler stream 按当前观测模式消费完成的值任务。</returns>
[Benchmark(Baseline = true)]
public ValueTask Stream_Baseline()
{
@ -157,6 +158,7 @@ public class StreamLifetimeBenchmarks
/// <summary>
/// 通过 GFramework.CQRS reflection stream binding 路径创建 stream并按当前观测模式消费。
/// </summary>
/// <returns>代表当前 reflection stream 按当前观测模式消费完成的值任务。</returns>
[Benchmark]
public ValueTask Stream_GFrameworkReflection()
{
@ -183,6 +185,7 @@ public class StreamLifetimeBenchmarks
/// <summary>
/// 通过 generated stream invoker provider 预热后的 GFramework.CQRS runtime 创建 stream并按当前观测模式消费。
/// </summary>
/// <returns>代表当前 generated stream 按当前观测模式消费完成的值任务。</returns>
[Benchmark]
public ValueTask Stream_GFrameworkGenerated()
{
@ -209,6 +212,7 @@ public class StreamLifetimeBenchmarks
/// <summary>
/// 通过 MediatR 创建 stream并按当前观测模式消费作为外部对照。
/// </summary>
/// <returns>代表当前 MediatR stream 按当前观测模式消费完成的值任务。</returns>
[Benchmark]
public ValueTask Stream_MediatR()
{

View File

@ -145,6 +145,7 @@ public class StreamingBenchmarks
/// <summary>
/// 通过 GFramework.CQRS runtime 创建 stream并按当前观测模式消费。
/// </summary>
/// <returns>按当前观测模式完成 stream 消费后的等待句柄。</returns>
[Benchmark]
public ValueTask Stream_GFrameworkCqrs()
{

View File

@ -12,7 +12,7 @@ CQRS 迁移与收敛。
## 当前恢复点
- 恢复点编号:`CQRS-REWRITE-RP-137`
- 恢复点编号:`CQRS-REWRITE-RP-138`
- 当前阶段:`Phase 8`
- 当前 PR 锚点:`PR #349已于 2026-05-12 合并到 origin/main`
- 当前结论:
@ -27,6 +27,17 @@ CQRS 迁移与收敛。
- 本轮继续按 `$gframework-batch-boot 50` 协调 subagent围绕 benchmark 文档与 startup parity 做两波窄切片:
- 已提交 `f346110a``StreamStartupBenchmarks``Mediator` startup parity
- 待收尾提交:`StreamingBenchmarks` 的 XML 文档补齐与 `GFramework.Cqrs.Benchmarks/README.md` 的 stream startup / gap 同步
- 在当前恢复点继续推进第 2 波 benchmark XML 契约收口,范围严格限定为公开 benchmark 方法缺失的 `<returns>` 文档:
- 主线程:`StreamingBenchmarks.cs``NotificationBenchmarks.cs``ai-plan/public/cqrs-rewrite/**`
- worker`StreamLifetimeBenchmarks.cs``StreamInvokerBenchmarks.cs``NotificationFanOutBenchmarks.cs`
- 启动第 2 波前,当前分支相对 `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)` 的已提交 branch diff 为 `5 files / 177 lines`,远低于 `$gframework-batch-boot 50` 的文件阈值;本轮是否继续主要由 context-budget / reviewability 决定,而不是 branch-size 预算。
- 第 3 波继续沿同一模式扩到 request 系 benchmark XML 契约收口,并已由 worker 分别提交:
- `555c7c07``RequestBenchmarks.cs``RequestPipelineBenchmarks.cs`
- `ab422b05``RequestInvokerBenchmarks.cs``RequestLifetimeBenchmarks.cs`
- 另有 `RequestStartupBenchmarks.cs` 已完成 `<returns>` 收口,待与主线程未提交切片一并收尾
- 当前已决定在第 3 波后停在自然边界,而不是继续开启第 4 波:
- branch-size 仍远低于 `50 files`
- 但剩余候选已不比当前波次更低风险,继续机械扩批会降低 reviewability并推高当前上下文负担
- tests 侧此前已补齐并提交:
- `CqrsRegistrationServiceTests`:补空输入、空项过滤、稳定键排序与跨调用跳过边界
- `CqrsHandlerRegistrarTests``CqrsHandlerRegistrarFallbackFailureTests`
@ -44,6 +55,11 @@ CQRS 迁移与收敛。
- 当前分支:`feat/cqrs-optimization`
- 当前 PR`PR #349已合并当前分支暂无新的公开 PR`
- 当前写面:
- `GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/NotificationFanOutBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/RequestStartupBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/StreamInvokerBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/StreamLifetimeBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/StreamStartupBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/README.md`
@ -51,16 +67,19 @@ CQRS 迁移与收敛。
- `ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
- 当前基线:
- `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)`
- 当前已提交 branch diff`1 file / 60 lines`
- 当前工作树尚有 2 个未提交收尾文件:`StreamingBenchmarks.cs``GFramework.Cqrs.Benchmarks/README.md`
- 当前已提交 branch diff`9 files / 143 lines`
- 当前分支比 `origin/main``4` 个提交:`f346110a``a016e3d4``ab422b05``555c7c07`
- 当前未提交面由 notification / stream / request-startup 的 XML 契约补齐与 `ai-plan` 恢复点更新构成
- 本轮提交:
- `f346110a` `feat(cqrs-benchmarks): 补齐 stream startup 的 Mediator 对照路径`
- `ab422b05` `docs(cqrs-benchmarks): 补齐 request benchmark 返回值注释`
- `555c7c07` `docs(cqrs-benchmarks): 补齐 request benchmark 返回值文档`
## 当前风险
- `StreamStartupBenchmarks``Mediator` parity 目前只做了编译验证,尚未单独执行 benchmark 作业确认 startup 矩阵运行结果。
- `StreamLifetimeBenchmarks` 仍缺 `Mediator` parity该项涉及 `BenchmarkHostFactory` 与 compile-time lifetime 形状,不再是本轮低风险切片。
- 当前 worktree 仍有 2 个未提交文档/注释收尾文件;若不在同轮提交,下一次 `boot` 会同时面对已提交 benchmark 扩展与未提交文档漂移
- 本轮已在 request 系 benchmark XML 契约收口后主动停批次;若后续恢复,优先先提交当前未提交面,再决定是否开启 docs/README 或 smoke-run 下一阶段,而不是继续机械扩张 XML 批次
## 最近权威验证
@ -73,9 +92,10 @@ CQRS 迁移与收敛。
## 下一推荐步骤
1. 先提交 `StreamingBenchmarks.cs``GFramework.Cqrs.Benchmarks/README.md` 与本 tracking / trace 收尾,回到干净工作树。
2. 若继续 benchmark 波次,优先单独执行 `StreamStartupBenchmarks` 的最小 smoke run验证新加 `Mediator` startup 路径可运行。
3. 若后续还要扩 stream parity`StreamLifetimeBenchmarks` 视为跨文件设计任务,而不是继续按“单文件低风险切片”处理。
1. 串行运行 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release``python3 scripts/license-header.py --check --paths ...``git diff --check`,作为当前自然停点的权威收尾验证。
2. 提交当前未提交的 notification / stream / request-startup XML 契约与 `ai-plan` 更新,回到干净工作树。
3. 若后续继续 benchmark 波次,优先单独执行 `StreamStartupBenchmarks` 的最小 smoke run验证新加 `Mediator` startup 路径可运行。
4. 若后续还要扩 stream parity`StreamLifetimeBenchmarks` 视为跨文件设计任务,而不是继续按“单文件低风险切片”处理。
## 活跃文档

View File

@ -7,6 +7,69 @@ SPDX-License-Identifier: Apache-2.0
## 2026-05-12
### 阶段benchmark XML 契约第 2 波收口CQRS-REWRITE-RP-138
- 延续 `$gframework-batch-boot 50`,基线保持为 `origin/main @ 2b2bec65 (2026-05-12 11:49:39 +0800)`
- 第 2 波启动前,当前分支相对基线的已提交 branch diff 为 `5 files / 177 lines`,明显低于 `50 files` 阈值;本轮继续与否的主停止信号仍是 context-budget / reviewability。
- 主线程本地盘点 `GFramework.Cqrs.Benchmarks/Messaging/*.cs` 的公开 `[Benchmark]` 方法后,确认当前仍有一批与既有收口模式一致的 XML `<returns>` 缺口:
- `StreamingBenchmarks.Stream_GFrameworkCqrs()`
- `NotificationBenchmarks` 的 3 个公开 benchmark 方法
- `NotificationFanOutBenchmarks` 的 5 个公开 benchmark 方法
- `StreamInvokerBenchmarks` 的 4 个公开 benchmark 方法
- `StreamLifetimeBenchmarks` 的 4 个公开 benchmark 方法
- 本波 accepted ownership
- 主线程
- `GFramework.Cqrs.Benchmarks/Messaging/StreamingBenchmarks.cs`
- `GFramework.Cqrs.Benchmarks/Messaging/NotificationBenchmarks.cs`
- `ai-plan/public/cqrs-rewrite/todos/cqrs-rewrite-migration-tracking.md`
- `ai-plan/public/cqrs-rewrite/traces/cqrs-rewrite-migration-trace.md`
- worker
- `StreamLifetimeBenchmarks.cs`
- `StreamInvokerBenchmarks.cs`
- `NotificationFanOutBenchmarks.cs`
- worker 回传验收结论:
- `StreamLifetimeBenchmarks.cs`
- 只补 `Stream_Baseline``Stream_GFrameworkReflection``Stream_GFrameworkGenerated``Stream_MediatR``<returns>`
- worker 自报 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release` 通过
- `StreamInvokerBenchmarks.cs`
- 只补 4 个公开 benchmark 方法的 `<returns>`
- worker 自报同一条 benchmark 工程 build 通过
- `NotificationFanOutBenchmarks.cs`
- 只补 5 个公开 benchmark 方法的 `<returns>`
- worker 自报 build 遇到 `CS2012``obj/Release/net10.0/GFramework.Cqrs.Benchmarks.dll` 被并发进程占用;该失败被判定为并发构建噪音,而不是代码语义问题
- 主线程局部实施:
- `StreamingBenchmarks.cs`
- 为 `Stream_GFrameworkCqrs()``<returns>`
- `NotificationBenchmarks.cs`
- 为 `PublishNotification_GFrameworkCqrs()``PublishNotification_MediatR()``PublishNotification_Mediator()``<returns>`
- 当前下一步:
- 主线程串行执行 benchmark 工程 Release build消除 worker 并发写 `obj/Release` 带来的验证噪音
- 若串行验证通过,决定是在当前自然停点提交收尾,还是继续 request 侧 XML 契约的下一波低风险批处理
### 阶段request benchmark XML 契约第 3 波收口后停在自然边界CQRS-REWRITE-RP-138
- 第 2 波串行验证通过后,继续用 3 个 worker 扩展 request 系 benchmark 的同类 `<returns>` 收口:
- `RequestStartupBenchmarks.cs`
- `RequestBenchmarks.cs` + `RequestPipelineBenchmarks.cs`
- `RequestInvokerBenchmarks.cs` + `RequestLifetimeBenchmarks.cs`
- worker 回传与 acceptance
- `RequestStartupBenchmarks.cs`
- 只补公开 benchmark 方法缺失的 `<returns>`
- worker 自报 `dotnet build GFramework.Cqrs.Benchmarks/GFramework.Cqrs.Benchmarks.csproj -c Release` 通过
- `RequestBenchmarks.cs` + `RequestPipelineBenchmarks.cs`
- 只补公开 benchmark 方法缺失的 `<returns>`
- worker 自报 build 通过,并已提交:`555c7c07 docs(cqrs-benchmarks): 补齐 request benchmark 返回值文档`
- `RequestInvokerBenchmarks.cs` + `RequestLifetimeBenchmarks.cs`
- 只补公开 benchmark 方法缺失的 `<returns>`
- worker 自报 build 通过,并已提交:`ab422b05 docs(cqrs-benchmarks): 补齐 request benchmark 返回值注释`
- 第 3 波后主线程 stop decision
- 不再开启第 4 波 XML 契约批处理
- 原因不是 branch-size 阈值耗尽;当前分支相对 `origin/main` 仍只有 `9 files / 143 lines`
- 停止原因是 context-budget / reviewability剩余候选已不比当前波次更低风险继续机械扩批收益下降
- 当前下一步:
- 只做主线程未提交面的串行验证与收尾提交
- 将干净工作树作为下一次 `boot` 的默认恢复目标
### 阶段stream startup parity 与文档收尾CQRS-REWRITE-RP-137
- 按 `$gframework-batch-boot 50` 恢复后,先重新执行 `$gframework-pr-review`