perf(ci): go-hub-test 的分片划分按实测成本重排——internal/repository 一个包就占 hub-server race 测试成本的 54.4%(227.7s / 418.8s),而 NR % 2 把它塞进 shard 2 ⇒ shard 2 在 14/14 次实测 CI run 里都是慢的那一半(中位 +119s、最大 +177s);改成它独占 shard 1 后两片 load 从 310.5/108.3 收到 227.7/191.1(spread 202.3s → 36.5s),不新增任何 job(#2251,ADR-032) - #2309
Merged
Conversation
…ver race 测试成本的 54.4%(227.7s / 418.8s),而 NR % 2 把它塞进 shard 2 ⇒ shard 2 在 14/14 次实测 CI run 里都是慢的那一半(中位 +119s、最大 +177s);改成它独占 shard 1 后两片 load 从 310.5/108.3 收到 227.7/191.1(spread 202.3s → 36.5s),不新增任何 job(#2251,ADR-032) ## 这条为什么值得做(Objective D 的量化目标已经达成,这是达成之后实测出来的**新**最长杆) #2300 把 `@agenthub/workbench` coverage job 从实测中位 **441s** 打到 **259s(−41.3%)**, 「≥40% / ≤4m30s」的目标已经过了(自测 15 次 pre-#2300 run 得到的基线,不是沿用 7m31s 口径)。 过了之后**极换人了**,所以重新量了一遍 43 次 run 的逐 job 时间: * FE-only PR 已经变成 `frontend-required`(5/9) 与 `windows-frontend`(4/9) 的**双极平局** (中位差 20s)⇒ workbench coverage 再分片只能把 PR 墙钟中位从 289s 推到 275s(**−4.8%**, 9 次里 4 次收益恰好为 0),却要把叶子数 15→19、两个重叠 FE-only PR 30→38 去撞实测 ~20 的 账号级并发上限。**分片 DEFERRED**,触发条件写进 ADR-032(该 job 墙钟中位 ≥ ~5m10s)。 * Go-touching PR 的极是 `backend-required`,而它被 `go-hub-test` 的分片失衡顶着: **shard 2 在 14/14 次实测 run 里都更慢**(post-#2300 窗口 18/18),中位 **+119s**(另一个口径 中位 |Δ| 2m02s)、最大 +177s / 3m20s(`33807478121`:6m03s vs 2m43s,把 `backend-required` 推到 +6m52s)。这是当前**唯一「零 runner 成本、每个 Go PR 都拿得到」**的杠杆。 ## 成因是实测的,不是「看代码觉得不均」 用 CI 同款 flag 逐包串行测(`go test ./... -count=1 -short -race -p 1 -parallel 1`,本机 Kunpeng ARM64 4C8G): | | 值 | |---|---| | hub-server 包数 / 总成本 | 52 / **418.81s** | | `internal/repository` 一个包 | **227.67s = 54.4%** | | 次重的三个 | `internal/middleware` 36.59s、`internal/service/auth` 25.01s、`internal/service/agent` 16.90s | | `NR % 2` 现状(shard1=偶数 NR / shard2=奇数 NR) | shard1 **108.3s** / shard2 **310.5s**,spread **202.3s** | | `repository` 的 `go list` 位置 | **第 15 位(奇数)⇒ 落 shard 2** | | 改后(shard1 = 该包独占 / shard2 = 其余 51 个) | **227.7s / 191.1s**,spread **36.5s** | 两个方向都被独立证据夹住:**shard 2 更慢**是 14/14(另一窗口 18/18)次 CI 实测, **shard 2 更重的原因就是这个包**是本地逐包实测。 **227.7s 同时是硬下限**:任何包粒度切分都不可能把最重的一片压到「单个包自己的成本」以下, 所以 LPT-3 的最重片还是 227.7s —— 第 3 个 shard 在这里买不到任何东西,只多烧一个 runner。 这也是为什么选 k=2 而不是 k=3:账号级并发上限实测 ~20,Go+FE run 已经峰值 18–20, 正是历史上 6 次饿死发生的形状。 ## 硬编码一个包路径会不会腐烂?——fail-closed,不会静默 如果 `internal/repository` 被改名/移动/拆分,shard 1 就收到 **0 个包**,而既有的守卫 `if [ -z "$SHARD_PKGS" ]; then echo "::error::shard N received 0 packages"; exit 1; fi` 会**硬报错**。也就是说这个常量腐烂的第一时间 CI 就红,而不是让两片悄悄失衡两个月。 再加 `verify-ci-gates.py` 三条断言(必须 pin 该包 / 不得退回 `NR % 2` / 必须保留 0-package 守卫)与 `verify-ci-gates.Tests.py` 两发变异自测(case 30/31),自测 39 → **41 全绿**, 且 `test_unmutated_workflow_passes` 证明未变异副本仍 rc=0(无假红)。 ## `go-edge-test` 刻意**不动**(同样实测过,不是没看) 同一套 flag 测 edge:35 包 / **143.96s**,最重 `internal/lifecycle` 34.57s = **24.0%** ⇒ **没有支配包可 pin**。现状 spread 29.1s load(shard1 偶数 NR = 86.5s vs 57.4s, 这正好解释 CI 上「edge shard 2 在 14/14 次里更快、中位 −46.5s」),LPT-2 能省 14.1s load 且包数天然 18/18 平衡——**但 `go-edge-test` 从来不是 `backend-required` 的极** (2m39s vs `go-hub-test` 4m51s),省下的时间到不了 PR 墙钟。所以本轮不改, 触发条件(edge-test 成为 backend 极)与全部数字写进 checks.yml 就地注释 + ADR-032(b)。 ## 方法学教训(写进 ADR-032 ⑤,防下次重推) **不带 `-race` 测出来的成本分布与 CI 完全不同**:同一台机器上 `go test -short -count=1 -p 1`(无 race)给出的是 `internal/middleware` 34.83s = 31%、 `internal/repository` 只占 11.11s = **9.9%**,据此会得出「shard 1 更重」的**相反**结论。 加上 `-race` 后 repository 涨到 227.67s(**20.5×**,race 检测器对这个包的放大远超其它包), 方向才与 28/28 次 CI 观察一致。⇒ 任何 shard 重排都必须用 CI 同款 flag 逐包测。 ## 同批落地的裁决 `docs/decisions.md` 新增 **ADR-032**(CI 反馈回路):① 目标已达成的自测口径与机制证据; ② stretch ≤3m **不做**(单 runner 下限已 255s,再快只能删测试工作量);③ workbench 分片 **DEFERRED** + 可证伪的触发条件;④ 换人之后的四个极按优先级((a) 本 PR 实施 / (b) edge 保持轮转 / (c) `windows-frontend` ~75s/leg 环境准备税 DEFERRED,需一次真实 CI 实验, 并**禁止**用砍掉 Windows leg 的 `Production build` 换 47–50s——那是每个 PR 唯一证明 desktop `tsc && vite build` 能过的地方 / (d) 两个前端杠杆严格互补、单独都不划算);⑤ 方法学。 `docs/governance/verifier-map.md` 的 ci-gates 行补上「Go 分片划分也是政策」。 Co-authored-by: Cursor <cursor@vectorcontrol.tech>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…3m49s/3m28s(spread 21s,对照基线中位 +119s)⇒ 矩阵跨度 −62s,落在预测 −40…−70s 区间;含 1 个包的那片反而较慢 21s,说明 link 成本随包数增长确实存在但比 load 失衡小一个数量级;同 run 的 go-edge-test 未改且仍非 backend 极,再次支持 ADR-032(b) 的「不动」 Co-authored-by: Cursor <cursor@vectorcontrol.tech>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这条为什么值得做(Objective D 的量化目标已经达成,这是达成之后实测出来的新最长杆)
#2300 把
@agenthub/workbenchcoverage job 从实测中位 441s 打到 259s(−41.3%),「≥40% / ≤4m30s」的目标已经过了(自测 15 次 pre-#2300 run 得到的基线,不是沿用 7m31s 口径)。
过了之后极换人了,所以重新量了一遍 43 次 run 的逐 job 时间:
frontend-required(5/9) 与windows-frontend(4/9) 的双极平局(中位差 20s)⇒ workbench coverage 再分片只能把 PR 墙钟中位从 289s 推到 275s(−4.8%,
9 次里 4 次收益恰好为 0),却要把叶子数 15→19、两个重叠 FE-only PR 30→38 去撞实测 ~20 的
账号级并发上限。分片 DEFERRED,触发条件写进 ADR-032(该 job 墙钟中位 ≥ ~5m10s)。
backend-required,而它被go-hub-test的分片失衡顶着:shard 2 在 14/14 次实测 run 里都更慢(post-perf(workbench-test): 消融 setup.ts 的 lazy 页面预热——前提在生产代码里已不成立(WorkbenchRoutes 是静态 import)、6 个 import 全部 5s 超时后 EnvironmentTeardownError,却给 169 个测试文件每个 beforeAll 平白加 ~5s(#2251 slice 3 最长杆的 37~40%) #2300 窗口 18/18),中位 +119s(另一个口径
中位 |Δ| 2m02s)、最大 +177s / 3m20s(
33807478121:6m03s vs 2m43s,把backend-required推到 +6m52s)。这是当前**唯一「零 runner 成本、每个 Go PR 都拿得到」**的杠杆。
成因是实测的,不是「看代码觉得不均」
用 CI 同款 flag 逐包串行测(
go test ./... -count=1 -short -race -p 1 -parallel 1,本机Kunpeng ARM64 4C8G):
internal/repository一个包internal/middleware36.59s、internal/service/auth25.01s、internal/service/agent16.90sNR % 2现状(shard1=偶数 NR / shard2=奇数 NR)repository的go list位置两个方向都被独立证据夹住:shard 2 更慢是 14/14(另一窗口 18/18)次 CI 实测,
shard 2 更重的原因就是这个包是本地逐包实测。
227.7s 同时是硬下限:任何包粒度切分都不可能把最重的一片压到「单个包自己的成本」以下,
所以 LPT-3 的最重片还是 227.7s —— 第 3 个 shard 在这里买不到任何东西,只多烧一个 runner。
这也是为什么选 k=2 而不是 k=3:账号级并发上限实测 ~20,Go+FE run 已经峰值 18–20,
正是历史上 6 次饿死发生的形状。
硬编码一个包路径会不会腐烂?——fail-closed,不会静默
如果
internal/repository被改名/移动/拆分,shard 1 就收到 0 个包,而既有的守卫if [ -z "$SHARD_PKGS" ]; then echo "::error::shard N received 0 packages"; exit 1; fi会硬报错。也就是说这个常量腐烂的第一时间 CI 就红,而不是让两片悄悄失衡两个月。
再加
verify-ci-gates.py三条断言(必须 pin 该包 / 不得退回NR % 2/ 必须保留 0-package守卫)与
verify-ci-gates.Tests.py两发变异自测(case 30/31),自测 39 → 41 全绿,且
test_unmutated_workflow_passes证明未变异副本仍 rc=0(无假红)。go-edge-test刻意不动(同样实测过,不是没看)同一套 flag 测 edge:35 包 / 143.96s,最重
internal/lifecycle34.57s = 24.0%⇒ 没有支配包可 pin。现状 spread 29.1s load(shard1 偶数 NR = 86.5s vs 57.4s,
这正好解释 CI 上「edge shard 2 在 14/14 次里更快、中位 −46.5s」),LPT-2 能省 14.1s load
且包数天然 18/18 平衡——但
go-edge-test从来不是backend-required的极(2m39s vs
go-hub-test4m51s),省下的时间到不了 PR 墙钟。所以本轮不改,触发条件(edge-test 成为 backend 极)与全部数字写进 checks.yml 就地注释 + ADR-032(b)。
方法学教训(写进 ADR-032 ⑤,防下次重推)
不带
-race测出来的成本分布与 CI 完全不同:同一台机器上go test -short -count=1 -p 1(无 race)给出的是internal/middleware34.83s = 31%、internal/repository只占 11.11s = 9.9%,据此会得出「shard 1 更重」的相反结论。加上
-race后 repository 涨到 227.67s(20.5×,race 检测器对这个包的放大远超其它包),方向才与 28/28 次 CI 观察一致。⇒ 任何 shard 重排都必须用 CI 同款 flag 逐包测。
同批落地的裁决
docs/decisions.md新增 ADR-032(CI 反馈回路):① 目标已达成的自测口径与机制证据;② stretch ≤3m 不做(单 runner 下限已 255s,再快只能删测试工作量);③ workbench 分片
DEFERRED + 可证伪的触发条件;④ 换人之后的四个极按优先级((a) 本 PR 实施 /
(b) edge 保持轮转 / (c)
windows-frontend~75s/leg 环境准备税 DEFERRED,需一次真实 CI 实验,并禁止用砍掉 Windows leg 的
Production build换 47–50s——那是每个 PR 唯一证明 desktoptsc && vite build能过的地方 / (d) 两个前端杠杆严格互补、单独都不划算);⑤ 方法学。docs/governance/verifier-map.md的 ci-gates 行补上「Go 分片划分也是政策」。Co-authored-by: Cursor cursor@vectorcontrol.tech