Pull Request已成功合入, 合并人@VaynNecol
(感谢 WangZijun 的贡献)Performance Regression Report
Time unit: ms. Each reported value is the mean of 5 measured runs.
Profile - Windows: 4 physical CPU cores, 8 logical CPU cores, 32 GiB RAM
- Serial:
1 worker - Parallel:
8 workers
| Project | Benchmark Serial first | Benchmark Serial warm | Benchmark Parallel first | Benchmark Parallel warm | Updated Serial first | Updated Serial warm | Updated Parallel first | Updated Parallel warm |
|---|---|---|---|---|---|---|---|---|
| bot-compass 263 files / 115,583 NBNC |
1,868.80 | 1,461.92 | 492.01 | 556.38 | 1,985.08 | 1,250.71 | 413.49 | 426.61 |
| bot-forge 64 files / 25,516 NBNC |
2,069.39 | 425.53 | 210.72 | 200.05 | 386.00 | 355.03 | 177.13 | 185.28 |
| bot-gate 59 files / 30,848 NBNC |
1,622.89 | 431.08 | 239.69 | 233.23 | 452.89 | 427.31 | 248.20 | 221.17 |
| bot-metric 29 files / 25,074 NBNC |
817.70 | 375.08 | 202.30 | 234.58 | 455.15 | 421.56 | 226.33 | 220.20 |
| rust 2,818 files / 828,622 NBNC |
65,293.90 | 14,515.00 | 3,221.37 | 3,241.18 | 12,399.67 | 12,188.37 | 2,686.61 | 2,549.23 |
Profile delta
| Project | Serial first | Serial warm | Parallel first | Parallel warm |
|---|---|---|---|---|
| bot-compass | +116.27 (+6.22%) | -211.21 (-14.45%) | -78.51 (-15.96%) | -129.78 (-23.32%) |
| bot-forge | -1,683.39 (-81.35%) | -70.50 (-16.57%) | -33.59 (-15.94%) | -14.77 (-7.38%) |
| bot-gate | -1,170.00 (-72.09%) | -3.77 (-0.87%) | +8.51 (+3.55%) | -12.07 (-5.17%) |
| bot-metric | -362.56 (-44.34%) | +46.48 (+12.39%) | +24.03 (+11.88%) | -14.39 (-6.13%) |
| rust | -52,894.24 (-81.01%) | -2,326.63 (-16.03%) | -534.76 (-16.60%) | -691.94 (-21.35%) |
Result
Five-project aggregate from the required full benchmark/updated runs:
- Serial first:
71,672.69 ms->15,678.79 ms(-55,993.91 (-78.12%)). - Serial warm:
17,208.61 ms->14,642.97 ms(-2,565.64 (-14.91%)). - Parallel first:
4,366.09 ms->3,751.77 ms(-614.32 (-14.07%)). - Parallel warm:
4,465.43 ms->3,602.49 ms(-862.94 (-19.32%)).
Alternating A/B confirmation (baseline and candidate run in alternating order to limit host drift):
-
Serial first:
14,443.48 ms->14,465.59 ms(+22.11 (+0.15%)). -
Serial warm:
14,727.47 ms->14,666.90 ms(-60.57 (-0.41%)). -
Parallel first:
3,863.03 ms->3,698.30 ms(-164.73 (-4.26%)). -
Parallel warm:
3,870.51 ms->3,706.41 ms(-164.10 (-4.24%)). -
Result: no stable performance regression was observed. Small positive and negative paired deltas vary by strategy; the required full benchmark aggregates are non-regressed in all four strategies.
-
Analysis semantics were unchanged for all five projects: file and NBNC totals match (
True).
Common configuration
- Baseline revision:
4a2bc49230372439dad42565cae68577c47fce9c(main) - Updated revision:
b4453ae2fd06acc5f085d5d4859b42682d308521 scope:reachableaggregation:physicalformat:jsoncache_policy:cold_then_filesystem_warmwarm_runs:5workers:1,8- Toolchain:
rustc 1.98.0-nightly (d595fce01 2026-06-02) - Both revisions used isolated release binaries built with
--locked. - Evidence:
D:\MetricOpt\docs\perf_res\issue_16\benchmark.json,updated.json,paired_baseline.json, andpaired_candidate.json.


xuanwu/bot-metric:main,94404b56-Merge branch 'main' into issue_16_22xuanwu/bot-metric:main,94404b56-Merge branch 'main' into issue_16_22评审结论
当前 issue_16_22 分支已实现两个 Issue 的主要用户可见目标:
- Issue #16:超时报告新增
compiler_run.timed_out = true,BM302 消息明确包含timeout,退出码124和partial语义保持不变。 - Issue #22:文档明确 SARIF 的静态 finding 与 compiler diagnostic 共用
runs[].results,并规定按ruleId/properties分类,不能依赖数组位置。
但仍有两个 P1 工程问题,因此当前 PR 不建议直接合并。
P1:Windows 超时没有终止完整进程树
Unix 使用进程组终止:
libc::kill(-(child.id() as i32), libc::SIGKILL)
但 Windows 路径仍然只是:
child.kill()
见 compiler.rs。
Child::kill() 只保证终止直接启动的 Cargo 进程,不保证终止其启动的 rustc、build script 或其他子进程。更严重的是,子进程可能继续持有 stdout/stderr 管道,而 run_command 随后会等待两个 reader thread 结束,导致:
--compiler-timeout-secs在 Windows 上不能形成真实耗时上界;- 长时间运行的 build script 可能在 Cargo 被杀后继续运行;
- reader thread 可能继续阻塞;
- 现有测试仍可能在 build script 自然退出后通过,掩盖进程树未清理的问题。
当前只完成了 Windows 交叉编译和 Clippy,没有在 Windows 原生执行这个测试。
建议使用 Windows Job Object,并设置 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,把 Cargo 及其后代放入同一个 Job;同时增加原生 Windows 验证,断言实际耗时接近配置的 timeout,并验证没有残留子进程。
P1:timed_out 未进入 1.2.1 Schema 契约
运行时已经正式输出:
"compiler_run": {
"exit_code": 124,
"timed_out": true
}
字段定义见 report.rs。
但 analysis-report-1.2.1.json 没有声明 compiler_run,更没有声明:
commandtoolchainexit_codetimed_outoutput_truncateddiagnostic_records_truncated
当前 Schema 因顶层 additionalProperties: true 仍会接受报告,但这只代表“没有拒绝未知字段”,不能证明 Schema 已描述新增机器契约。代码和文档要求下游使用 1.2.1 Schema 验证报告,因此新增的结构化超时字段必须进入 Schema,并补充实际报告的 Schema 验证测试。
已确认:
- Cargo 超时状态可以结构化消费;
- BM302 不再要求用户理解
124惯例; partial和退出码3保持不变;- Cargo/Clippy 共用传播路径,rustc 路径也写入
output.timed_out; - 旧报告缺少
timed_out时默认反序列化为false; false不序列化,兼容原有成功报告。
结论:功能目标已解决,但 Schema 和 Windows 进程树边界尚未闭环。
Issue #22 复核
生产 SARIF serializer 的实际顺序为:
全部 finding
→ 全部 compiler diagnostic
编译器诊断输出:
{
"ruleId": "rustc.diagnostic",
"properties": {
"code": "E0308"
}
}
文档已明确:
- 两类结果共用
runs[].results; - 顺序仅用于确定性输出;
- 下游不得通过数组位置分类;
- finding 使用原始规则 ID;
- compiler diagnostic 使用
rustc.diagnostic; - 原始 rustc/lint code 位于
properties.code。
现有流式 SARIF 与兼容投影等价性测试也覆盖了包含 finding 和 compiler diagnostic 的报告。
结论:Issue #22 可以认为已经闭环。


Performance Regression Report
Time unit: ms. Each strategy uses one first run followed by five warm runs.
Strict rule: any updated cell slower than the Web benchmark is considered a regression.
Profile A — 16 GB RAM · 8 CPU cores
Approximation on the current host:
- Serial:
1 worker - Parallel:
8 workers - No physical 16 GB memory limit was applied.
| Project | Benchmark Serial first |
Benchmark Serial warm |
Benchmark Parallel first |
Benchmark Parallel warm |
Updated Serial first |
Updated Serial warm |
Updated Parallel first |
Updated Parallel warm |
|---|---|---|---|---|---|---|---|---|
| bot-compass 263 files / 115,583 NBNC |
318.61 | 316.15 | 125.43 | 121.77 | 374.12 | 323.53 | 121.89 | 122.18 |
| bot-forge 67 files / 27,201 NBNC |
91.54 | 89.18 | 49.49 | 50.02 | 105.90 | 97.30 | 51.09 | 54.00 |
| bot-gate 62 files / 38,521 NBNC |
110.75 | 112.11 | 62.57 | 63.56 | 133.36 | 127.05 | 72.64 | 66.80 |
| bot-metric 29 files / 26,143 NBNC |
89.05 | 87.18 | 55.16 | 53.86 | 91.86 | 90.61 | 53.21 | 58.87 |
| rust 2,817 files / 826,803 NBNC |
2,893.75 | 2,886.90 | 742.62 | 765.04 | 3,359.61 | 2,964.05 | 748.30 | 772.43 |
Profile A delta
| Project | Serial first | Serial warm | Parallel first | Parallel warm |
|---|---|---|---|---|
| bot-compass | +55.51 (+17.4%) | +7.38 (+2.3%) | −3.54 (−2.8%) | +0.41 (+0.3%) |
| bot-forge | +14.36 (+15.7%) | +8.12 (+9.1%) | +1.60 (+3.2%) | +3.98 (+8.0%) |
| bot-gate | +22.61 (+20.4%) | +14.94 (+13.3%) | +10.07 (+16.1%) | +3.24 (+5.1%) |
| bot-metric | +2.81 (+3.2%) | +3.43 (+3.9%) | −1.95 (−3.5%) | +5.01 (+9.3%) |
| rust | +465.86 (+16.1%) | +77.15 (+2.7%) | +5.68 (+0.8%) | +7.39 (+1.0%) |
Profile A result:
- Non-regressed cells:
2 / 20 - Regressed cells:
18 / 20 - Strict result: failed
Profile B — Apple M5 Max · 64 GB RAM
Measured on the current host:
- Serial:
1 worker - Parallel:
18 workers
| Project | Benchmark Serial first |
Benchmark Serial warm |
Benchmark Parallel first |
Benchmark Parallel warm |
Updated Serial first |
Updated Serial warm |
Updated Parallel first |
Updated Parallel warm |
|---|---|---|---|---|---|---|---|---|
| bot-compass 263 files / 115,583 NBNC |
318.61 | 316.15 | 96.53 | 97.28 | 374.12 | 323.53 | 101.10 | 101.65 |
| bot-forge 67 files / 27,201 NBNC |
91.54 | 89.18 | 47.34 | 48.13 | 105.90 | 97.30 | 50.74 | 50.88 |
| bot-gate 62 files / 38,521 NBNC |
110.75 | 112.11 | 60.19 | 59.64 | 133.36 | 127.05 | 64.82 | 62.75 |
| bot-metric 29 files / 26,143 NBNC |
89.05 | 87.18 | 50.48 | 51.00 | 91.86 | 90.61 | 53.80 | 53.43 |
| rust 2,817 files / 826,803 NBNC |
2,893.75 | 2,886.90 | 582.55 | 568.75 | 3,359.61 | 2,964.05 | 589.27 | 564.97 |
Profile B delta
| Project | Serial first | Serial warm | Parallel first | Parallel warm |
|---|---|---|---|---|
| bot-compass | +55.51 (+17.4%) | +7.38 (+2.3%) | +4.57 (+4.7%) | +4.37 (+4.5%) |
| bot-forge | +14.36 (+15.7%) | +8.12 (+9.1%) | +3.40 (+7.2%) | +2.75 (+5.7%) |
| bot-gate | +22.61 (+20.4%) | +14.94 (+13.3%) | +4.63 (+7.7%) | +3.11 (+5.2%) |
| bot-metric | +2.81 (+3.2%) | +3.43 (+3.9%) | +3.32 (+6.6%) | +2.43 (+4.8%) |
| rust | +465.86 (+16.1%) | +77.15 (+2.7%) | +6.72 (+1.2%) | −3.78 (−0.7%) |
Profile B result:
- Non-regressed cells:
1 / 20 - Regressed cells:
19 / 20 - Strict result: failed
Same-host A/B attribution
The branch was compared with a release build from the same-host main checkout.
| Project | 1 worker warm | 8 workers warm | 18 workers warm |
|---|---|---|---|
| bot-compass | −1.7% | −3.2% | −2.6% |
| bot-forge | −1.9% | −1.6% | −2.7% |
| bot-gate | +0.4% | +2.0% | −0.7% |
| bot-metric | −0.6% | +10.0% | +1.5% |
| rust | −1.6% | −1.1% | +1.1% |
The bot-metric · 8 workers warm result was remeasured with 10 interleaved runs:
main mean: 53.32 ms
issue_16_22: 53.16 ms
delta: −0.16 ms (−0.30%)
main median: 53.15 ms
issue_16_22: 52.61 ms
delta: −0.54 ms (−1.02%)
Interpretation
- The strict Web comparison failed because the Web values are historical v1.2.0 measurements and many updated cells are slower.
- The current project checkouts are not identical to the historical Web snapshot:
bot-forge: 67 files / 27,201 NBNCbot-gate: 62 files / 38,521 NBNCbot-metric: 29 files / 26,143 NBNCrust: 2,817 files / 826,803 NBNC
- Issue #16/#22 production changes are Windows-specific Job Object/compiler-timeout handling and are not executed by this macOS benchmark.
- Schema/version and documentation changes do not affect the source-analysis hot path.
- Same-host A/B testing found no sustained attributable performance regression.
- The isolated
bot-metric · 8 workersfluctuation disappeared during interleaved remeasurement. - Therefore, the strict historical Web gate fails, but this run does not provide evidence of a performance regression caused by
issue_16_22.
Run configuration
scope:reachableaggregation:physicalformat:jsonwarm_runs:5- Profile A:
1 / 8 workers - Profile B:
1 / 18 workers - Current host: Apple M5 Max, 18 cores, 64 GB RAM
- Physical 16 GB memory limit: not applied
- Toolchain: Rust 1.89.0 / Cargo 1.89.0
- Benchmark binary: Web v1.2.0 historical baseline
- Updated binary:
issue_16_22release build - Updated schema:
analysis-report-1.2.2.json


Scenario
Compiler timeouts were only identifiable through exit code 124, while mixed SARIF findings and compiler diagnostics lacked a documented consumer contract.
Changes
compiler_run.timed_outflag for Cargo, Clippy, and rustc providers while preserving exit code 124 and partial-result behavior.runs[].resultssequence and classification byruleId/propertiesinstead of array position.Verification
cargo fmt --all -- --checkcargo check --workspace --all-targets --lockedcargo clippy --workspace --all-targets --locked -- -D warningscargo test --workspace --all-targets --lockedFixes #16
Fixes #22