Skip to content

Latest commit

 

History

History
221 lines (154 loc) · 9.36 KB

File metadata and controls

221 lines (154 loc) · 9.36 KB

bench 改为「本地真跑、CI 不跑」:方案与 Linux 实测计划(2026-08-14)

状态:待 review,尚未实施。


0. 一句话

把 bench 从 CI 里整个删掉,改成一条本地可重复的命令产出数据;当前只承诺 Linux,其他平台在文档里明确标 (未测试);标准数据集固定为 3 轮


1. 为什么删 CI bench —— 不是因为它慢,是因为它测不到东西

删除的理由必须是事实,不是偏好。当前 bench/matrix.json 的账:

格子数 10
外部引擎臂总数 32
allow_failed 豁免的 12(37%)
其中 xmake 在测 4 / 豁免 6 —— 豁免多于在测
其中 cmake 在测 5 / 豁免 5

也就是说:一个自称「跨引擎对比」的矩阵,有三分之一的对比臂从未产出过数字,而 job 是绿的。这不是"还没修完",这是这个东西在 CI 上跑的形态本身就不成立:

  1. 共享 runner 上测的是 runner,不是引擎。 两核机器、邻居噪声、镜像随时更新。 同一份代码在 runner 上 cold 是 243s,在开发机上是 79s —— 三倍差距不来自 mcpp。
  2. 外部工具的缺口不是 mcpp 的缺陷,却由 mcpp 的 CI 承担。 xmake 编不了 libc++ 的 import std、bazel 的 MSVC 依赖扫描器坏掉、rules_cc 不支持 Windows PIC —— 每一个都要在 mcpp 的矩阵里挂一条豁免,而豁免越多,绿色越没意义。
  3. 一次矩阵约两小时,而它回答的问题("性能有没有退")在 PR 粒度上并不需要每次回答。 真正需要它的时刻是发版前做完一次优化后,那两个时刻都有人在场。

保留 CI 里的哪一部分:tests/e2e/230_bench_harness.sh(套件自身能构建、能跑出一份 合法报告)继续留在 e2e 里。删掉的是跑真实工作负载的那个矩阵,不是套件的自测。


2. 删掉什么、留下什么

删除

  • .github/workflows/bench.yml 整个文件

保留,但改变角色

  • bench/matrix.json —— 从「CI 跑哪些格子」变成「标准数据集的定义」。 这一点很关键:清单仍然只有一份,只是读它的人从 workflow 变成了本地脚本。
  • bench/src/** —— harness 本身不动。
  • bench/results/** —— 数据仍然入库。

新增

  • bench/run-standard.sh(名字待定)—— 读 matrix.json,跑当前平台的格子, 3 轮,输出到 bench/results/<date>-<os>-<arch>/。一条命令,不带参数也能跑。

必须同步改的守卫(否则删完 e2e 直接红)

  • tests/e2e/233_bench_matrix.sh 现在有 5 处读 .github/workflows/bench.yml: 第 48/53 行(存在性)、427(workflow 读 matrix.json)、438(--runs 与 dispatch 默认值)、475/480(runner 镜像不得内联)。这些检查的对象要从 workflow 换成 bench/run-standard.sh,判据不变:清单只有一份、脚本读它而不重复它
  • tests/e2e/232_workflow_syntax.sh 会少一个文件,无需改。

3. 标准数据集 —— 只承诺能证明的

3.1 平台

平台 承诺 README 写法
Linux x86_64 本次真实跑出 完整数据
macOS 不跑 (未测试)
Windows 不跑 (未测试)

(未测试) 不是 (不支持)。差别要在文档里写明:没有数据 ≠ 不能用,而 "曾经有过一版数据、但那版数据是在有缺陷的 harness 上取的"更要写明 —— 见 §5。

3.2 格子(Linux)

从现有 10 格里取 Linux 的 6 格,并去掉所有需要豁免的外部臂:

工作负载 编译器 引擎 说明
fixture gcc mcpp, cmake, xmake 三引擎,唯一能控制 variant 轴的地方
fixture clang mcpp, cmake, xmake, bazel 四引擎
mcpp-2026.8.11.3 gcc mcpp, xmake cmake 有未定案缺口 → 不列
mcpp-2026.8.11.3 clang mcpp, cmake xmake 有已复现缺口 → 不列
xlings-2026.8.11.2 gcc mcpp 两个外部臂都有缺口
xlings-2026.8.13.1 gcc mcpp 同上,与上一行成对(两种代码风格)

原则:标准集里不出现豁免。 一条臂要么在测,要么不在这张表里 —— 它的缺口写进 §5 的「已知缺口」清单,附证据。这样"标准数据"里的每一个数字都是真的跑出来的, 不需要读者去分辨哪些是豁免掉的。

3.3 轮次

3 轮(--runs 3),取中位数,同时记录 min/max。

理由:n=1 没有离散度,而现有 README 每张表都标 n=1 并附带"不要比较个位数字"的 警告 —— 那个警告本身就说明 n=1 不够。3 轮 × 6 格 × 5 场景在开发机上约 40–60 分钟, 是一个人可以在一次会话里跑完的量。

3.4 场景

沿用现有六个:cold / noop / touch-hub / touch-leaf / edit-body / edit-comment。真实工程略去 touch-leaf(现有 note 已说明:真实的树里没有 "没人 import 且足够稳定可以点名"的单元)。


4. 本地实测计划(Linux)

4.1 前置条件(脚本要检查并明确报错,而不是继续跑)

  1. 工具链载荷齐备:xim-x-gcc/16.1.0xim-x-llvm/22.1.8xim-x-binutilsxim-x-glibc
  2. 外部工具按 matrix.jsontools 钉住:cmake 4.0.2 / xmake 3.1.0 / bazel 9.2.0
  3. 子模块已 checkout(三个 pinned 工作负载)
  4. 依赖包已解包(mcpplibs.cmdline 等)—— 现在 cmake 臂会 FATAL_ERROR,好过静默少编

4.2 步骤

# 1. 构建被测的 mcpp 与 harness
mcpp build --release
cd bench && mcpp build --release && cd ..

# 2. 拉取钉住的工作负载
git submodule update --init

# 3. 跑标准集(一条命令,内部按 matrix.json 展开 Linux 的格子)
bash bench/run-standard.sh

# → bench/results/2026-08-14-linux-x86_64/*.json + report.md

4.3 记录什么

每份报告已经带 host(CPU 型号、核数、内存、是否异构)。再补两件:

  • 被测 mcpp 的版本与 commit —— 现在只记版本号,同一版本可以有不同 commit
  • 跑完的时间戳与总耗时 —— 用于判断两次数据是否可比

4.4 判据(跑完必须核对,不能只看退出码)

  1. 退出码 0
  2. failed 为 0、waived 为 0(标准集里不该有豁免)
  3. 每个 cold 都通过既有的两条不变量(vs 自身 noop ≥2×、vs 同侪 ≤20×)
  4. 三轮的 min/max 跨度不超过中位数的 ±20% —— 超了就是机器有噪声,数据不发布

5. README 要改成什么样

现在的 bench/README.md一份实验记录:900 行,大量"这里曾经错在哪"。 那些内容有价值,但它不是一个人第一次想跑 bench 时该读到的东西。

改成三层:

bench/README.md
├─ 一、怎么跑(前 40 行,可以照抄的命令)
├─ 二、标准数据(Linux 表格 + 其他平台标 (未测试))
└─ 三、方法与已知缺口(现有内容,往后放)

「怎么跑」必须是可重复的:给出完整命令序列、预期耗时、以及"跑完怎么判断这份 数据能不能用"(§4.4 的四条)。现在的 README 里这些信息散在 §6 和 §10。

已知缺口单独成节,每条写:现象、归属(我们的 / 上游的)、复现方式、试过什么。 当前应当列入:

缺口 归属 证据
xmake + libc++ 编不了真实工程的 import std 上游 本机复现,--sdk 与两种工具链都试过
cmake 在 CI runner 上 __CMAKE::CXX23 不可用 未定 外部可查项全部与能跑通的机器一致
cmake 读 xlings 依赖包时 manifest has no sources 我们的 本机 rc=0,runner 上某个 compat-x-*sources;具体包名待补
bazel MSVC 依赖扫描器 上游 rules_cc Windows 专有

中文版同步,并保留"以英文版为准"的声明。


6. 现有已发布数据怎么处理

bench/results/ 里已有 30 个 JSON。不删,但要在 README 里分层:

  • 标准数据:本次 Linux 实测那一份(3 轮),README 的表格只引用它
  • 历史数据:其余的,标注日期与当时的 harness 状态

⚠️ 特别地:bmi_schedule=on 那一列的旧数据是在 §8b 缺陷修复之前取的, touch-hub/edit-comment 两格量的工作比构建欠下的少(已在 README §8b 记录)。 本次重测应当把这一列一并重取,让标准表里不再混有修复前的数字。


7. 风险与取舍

取舍
CI 不再跑 bench 省两小时/次;不再用绿色掩盖 12 条豁免 性能回归不再自动发现
只承诺 Linux 数字都是真的 跨平台差异无数据
标准集不含豁免臂 表里每个数字都真跑过 表变小(32 臂 → 约 14 臂)

最大的失是第一条。缓解:把「发版前跑一次标准集」写进发布流程文档 (release-publish-pipeline 那条);优化类 PR 在描述里附本地数据。

不做的事:不搞"CI 里跑一个缩水版 bench"。缩水版会重新引入"绿色代表什么" 的模糊地带 —— 这正是要删掉它的原因。


8. 待 review 的决策点

  1. bench/run-standard.sh 这个名字与位置,是否放在 bench/
  2. 标准集的格子清单(§3.2)是否合适 —— 尤其是否要保留 xlings 的两格 (它们只有 mcpp 一条臂,是"两种代码风格对比"而非"引擎对比")
  3. 3 轮是否够;要不要对 cold 单独加轮次
  4. bench/matrix.json 是否继续承载"标准集定义",还是另起一个更小的文件
  5. §6 的历史数据:保留还是清理到只剩标准集