Visitar URL original
perf(ci): give the heavier test lane the larger runner by Han5991 · Pull Request #6080 · meta/astryx · GitHub
Skip to content

perf(ci): give the heavier test lane the larger runner - #6080

Merged
cixzhang merged 1 commit into
meta:mainfrom
Han5991:ci/swap-test-lane-runners
Sep 7, 2026
Merged

cixzhang merged 1 commit into
meta:mainfrom
Han5991:ci/swap-test-lane-runners

Conversation

@Han5991

@Han5991 Han5991 commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Why

test-ui and test-node hold their runners the wrong way round relative to the work they carry.

lane runner job suite step
test-ui 2-core-ubuntu-arm 14m52s 834s
test-node 4-core-ubuntu 3m18s 165s

Run 34000689684 (main, success). Reproduced on 33994177354 (926s/189s) and 33980770638 (974s/194s), and on deploy runs 33980455596 and 33952374356.

The 4-core box is under the three-minute lane. The fifteen-minute lane — the one nearest the ~20 minute wall the lane comment itself describes — is on the 2-core arm box.

The number that put it there

The comment introduced with the lane split says:

node is the heavier lane — locally 570s against the ui project's 244s — so it takes the larger supported runner while ui stays on the 2-core arm box.

That comparison does not appear to be like-for-like. #6051's own validation notes record the node suite as run "with bounded workers"; the ui line carries no such note. And node is precisely the project that a bounded pool penalises — vitest.config.ts documents that it runs on the forks pool because CLI tests call process.chdir(), and that "several CLI suites spawn a fresh node bin/astryx.mjs per assertion (real process boundary)".

The CI numbers are hard to reconcile with 570s any other way: unbounded, the node lane finishes in 165s while also paying the cold ensureCoreBuilt() core build that a warm local tree skips (build-theme.data-tokens.test.mjs:117 — "ensureCoreBuilt() only checks that dist exists"). The local run had strictly less work and still took 3.5x longer.

I've rewritten the comment to state what CI measures, and to record why the local figure isn't comparable.

What this changes

Four runs-on: values, two in each workflow. deploy.yml carried the same allocation.

Nothing else moves. In particular the repo-wide guardrail steps stay on test-ui, so the "they ride the LIGHTER lane" claim is now simply corrected in place rather than acted on — they cost ~18s of an 892s job, and moving them is a separate change that isn't worth coupling to this one.

Verification

.github/scripts/ci-test-routing.test.mjs passes unchanged — 17/17. Both labels are already in KNOWN_RUNNERS (:47-52) and no assertion in the file binds a lane to a runner, which is why this needed no test edit.

The real verification is this PR's own CI run: it reports the swapped allocation directly, against the numbers above.

What this does not do

This does not close #4339's original criterion. On run 34000689684 test-ui finished 385s after build-sandbox, and the workflow ended 17s later — the test lane is still the critical path, just no longer a re-push casualty. Subdividing ui is the next lever and is deliberately not in this PR; a strategy: matrix inside the existing test-ui job passes all 17 contract cases, so it can land separately on measured numbers.

Filed because the headroom is thin: test-ui is at 14m52s against a wall its own comment puts at ~20 minutes, and the ui project went 439s → 834s in roughly three weeks.

@vercel

vercel Bot commented Sep 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Sep 7, 2026 3:24pm UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Sep 6, 2026
@github-actions github-actions Bot added community Authored by a community contributor (not on the eng/design team) needs:code-review High-risk change (new package/component/API) — needs human code review before merge labels Sep 6, 2026
@Han5991

Han5991 commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Measured

This PR's own CI run against a pull_request run on the same base. Both runs are pull_request, same suite, no test-file changes in this branch.

baseline 34000689684 this PR 34004880026 Δ
test-ui job 892s · 2-core-ubuntu-arm 521s · 4-core-ubuntu −371s / −41.6%
test-ui suite step 834s 459s −375s / −45.0%
test-node job 198s · 4-core-ubuntu 353s · 2-core-ubuntu-arm +155s / +78.3%
test-node suite step 165s 305s +140s / +84.8%
test gate (= slower lane) 892s 521s −371s / −41.6%
whole CI run 951s 615s −336s / −35.3%

Both lanes green.

What it settles

ui scales with cores; node less so. Doubling ui's cores took 45% off its suite step. Halving node's cost it 85% — real, but from a much smaller base. That ordering is the opposite of the one the lane comment encoded, and it is now measured on this CI rather than inferred.

test is no longer the critical path by any meaningful margin. On the baseline, test-ui finished 385s after build-sandbox. Here it finishes 22s after it (01:59:25Z vs 01:59:03Z). The gate and the longest build job now land together.

Headroom. test-ui goes from 14m52s to 8m41s against the ~20 minute wall the lane comment describes. That was the thing I was actually worried about — ui went 439s → 834s in about three weeks, and at 892s there were roughly five minutes left.

The cost, stated plainly

This is not free. Weighting each lane by its cores:

  • baseline: 892×2 + 198×4 = 2,576 core-seconds
  • this PR: 521×4 + 353×2 = 2,790 core-seconds

+8.3% core-seconds for −41.6% gate wall clock. If runner-seconds are the binding constraint rather than latency, that trade is arguable and I'd rather it be argued explicitly than hidden.

Follow-up this makes smaller

Sharding ui was the obvious next lever at 834s. At 459s it is no longer urgent, and I'd rather not spend the complexity until the number asks for it again. Recording the option here so it doesn't have to be rediscovered: a strategy: matrix inside the existing test-ui job passes all 17 cases in ci-test-routing.test.mjs unchanged.

Caveat

n=1 on each side. The baseline is consistent with the wider sample I looked at (test-ui 834–974s across 33994177354, 33980770638 and others), so 459s sits well outside that band — but it is still one run against one run.

github-actions Bot added a commit that referenced this pull request Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR
GitHub Pages may take up to a minute to hydrate after deploy.

🧪 Sandbox Preview

View Sandbox for this PR
GitHub Pages may take up to a minute to hydrate after deploy.

No new or modified components detected.

Bundle Size Summary

No component packages changed.

Accessibility Audit

Status: No accessibility violations detected.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

@cixzhang cixzhang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated against the exact CI workload. 4-core-ubuntu is the right non-default pool for test-ui: the PR run reduced the 384-file UI suite from 834s to 459s and the full job from 892s to 521s.

Keep pnpm vitest run --project ui without an explicit --maxWorkers. Vitest 4.1.10 deliberately uses availableParallelism() - 1 in run mode, so this gives the four-core runner three test workers plus coordinator/Vite headroom. Forcing 100% would add a fourth worker while each worker has a 4 GiB heap ceiling on a ~15 GiB runner, increasing OOM/flakiness risk. The measured 45% reduction confirms that the default pool is already using the added capacity effectively.

Please rebase after #6113 lands and preserve its positive-routing skip conditions; this runner swap is otherwise independent.

@github-actions github-actions Bot removed the needs:code-review High-risk change (new package/component/API) — needs human code review before merge label Sep 7, 2026
`test-ui` and `test-node` hold their runners the wrong way round relative
to the work they carry. The ui lane runs ~5x the node lane on CI, but ui
sits on `2-core-ubuntu-arm` while node holds `4-core-ubuntu`.

Run 34000689684 (main, 2026-09-06, success):

  test-ui     14m52s   2-core-ubuntu-arm   (suite step 834s)
  test-node    3m18s   4-core-ubuntu       (suite step 165s)

Reproduced on 33994177354 (926s/189s) and 33980770638 (974s/194s), and on
deploy runs 33980455596 and 33952374356.

The lane comment cites a local measurement in the other direction — node
570s against ui 244s. That comparison is not reproducible here. meta#6051's
validation notes record the node suite as run "with bounded workers"
while the ui suite carries no such note, and node is the project whose
cost is per-assertion `node bin/astryx.mjs` spawns under the forks pool
(vitest.config.ts) — the work a bounded pool serializes most. Unbounded on
CI the node lane finishes in 165s while also paying the cold
`ensureCoreBuilt()` core build that a warm local tree skips, so the local
run had strictly less work and still took 3.5x longer.

deploy.yml carried the same allocation and is swapped with it.

`.github/scripts/ci-test-routing.test.mjs` passes unchanged (17/17): both
labels are already in KNOWN_RUNNERS and no assertion binds a lane to a
runner.
@cixzhang
cixzhang force-pushed the ci/swap-test-lane-runners branch from a4d11e6 to c19ade7 Compare September 7, 2026 15:19
github-actions Bot added a commit that referenced this pull request Sep 7, 2026
@cixzhang
cixzhang merged commit 20d1a40 into meta:main Sep 7, 2026
27 checks passed
@Han5991
Han5991 deleted the ci/swap-test-lane-runners branch September 7, 2026 15:55
cixzhang added a commit that referenced this pull request Sep 7, 2026
Nine commits, no conflicts. Two touched files this branch also changes, both
auto-merged cleanly and re-read by hand:

- ci.yml gained a tooling_only lane (#6112, #6113) and moved the heavier test
  lane to a larger runner (#6080). The tooling lane is an exact two-file
  allowlist in change-scope.cjs, so it cannot claim this PR, and the
  accessibility additions — the widened check-components filter, the a11y-spec
  typecheck step, and the test:a11y-contract step in pr-a11y — all survived the
  merge intact;
- deploy.yml's a11y-spec typecheck step is intact.

The 0.6 breaking change (#6118) removes deprecated focus-hook options, an
isImeKeyEvent re-export, and useResizable pixel bounds. Nothing under Switch,
the stories, or internal/a11y-spec references any of them.

This branch was successfully deployed

1 active deployment
Preview — c19ade75 Deployed Sep 7, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot. community Authored by a community contributor (not on the eng/design team)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The test job is the CI critical path on re-pushes, merge queue, and main

2 participants