Repository navigation
CI perf: e2e fan-out — 23 e2e-macos + ~118 Linux e2e jobs/run, 82–87% under 2 min, 30–58% of job time is setup (~1,200 macOS + ~6,000 Linux job-min/day) #1172
Description
Measurement
Window: 2026-10-08 02:16Z to 19:36Z. All CI runs, from runs/<id>/jobs.
| Job family | Jobs/day | Job-min/day | Avg job | Jobs < 2 min | Setup-step share* |
|---|---|---|---|---|---|
e2e-macos (macOS) |
3,089 | 3,687 | 1.19 min | 87% | 31% |
e2e (Linux) |
40,429 | 87,114 | 2.15 min | 82% | 13% (11,266 min/day) |
e2e (Windows) |
5,790 | 7,153 | 1.24 min | 85% | 29% |
e2e-full (Linux) |
1,205 | 877 | 0.73 min | 99% | 38% |
* Setup-step share is the time in Set up job, Checkout, Download the e2e binaries, Complete job and Post steps. It does not count runner provisioning or queue time.
e2e-macos in merge_group runs: 23 legs. Summing each leg's p50, the jobs take 25.7 min, of which the test steps (Run …) are only 10.8 min. Examples per leg (p50 job / p50 test steps, n=68):
| Leg | Job | Test steps |
|---|---|---|
e2e_vendor_bun_build |
0.48 | 0.03 |
e2e_redirect_bun_build |
0.48 | 0.03 |
e2e_safety_pnpm |
0.62 | 0.07 |
e2e_redirect_uv_build |
0.55 | 0.08 |
e2e_nuget_dotnet_build |
0.78 | 0.13 |
e2e_vendor_maven_build |
2.12 | 0.52 |
e2e_redirect_maven_build |
1.90 | 0.33 |
The 3 Maven legs each install Maven separately.
Linux runner saturation. When Linux jobs started exceed about 3,000 per hour, Linux queue wait climbs:
| Hour (UTC) | Jobs started | p50 wait | p90 wait |
|---|---|---|---|
| 10-08 02Z | 2,574 | 7.3 min | 9.9 min |
| 10-08 03Z | 3,376 | 10.3 min | 17.2 min |
| 10-08 04Z | 2,961 | 6.3 min | 10.3 min |
| 10-08 11Z | 3,142 | 5.5 min | 9.9 min |
| 10-08 16Z | 3,664 | 3.5 min | 6.7 min |
Those queue minutes land directly on merge_group critical paths. e2e-macos itself waits p50 0.35 min, p90 5.2 min.
Example run: 37828932401, with 23 e2e-macos jobs and about 106 Linux e2e jobs.
Where the time goes
Each matrix leg pays these fixed costs before running about 5–60 s of tests:
- Runner provisioning.
- Set up job (about 0.1 min).
- Checkout.
- Downloading the 200 MB e2e-bin artifact (about 0.1 min on Linux, more on macOS).
- A toolchain install (Maven, dotnet, pip/uv, bun, vlt).
Root cause
The e2e, e2e-macos and e2e-full matrices give one job to each (suite × tool-version) pair. Since #1133, Linux merge_group runs have about 106–117 e2e jobs. Most legs finish in under a minute of test time, so per-job overhead dominates. Each leg also takes a separate runner slot from the ~20-slot macOS pool and the Linux pool.
Proposed fix
In .github/workflows/ci.yml, bin-pack the short legs. Leave the long Gradle legs alone; those are tracked separately.
-
e2e-macos: collapse the 23 rows into about 4 bins of roughly 3 test-minutes each, grouped by toolchain:- JVM: the 3 Maven legs share one Maven install, plus the dotnet leg.
- JS: bun, pnpm, vlt ×5, rush.
- Python: uv, pypi, vex pip/pipenv/hatch/poetry/pdm.
- npm.
Each bin runs its suites sequentially in one job, with one
Run e2e testsstep per suite, so the logs stay attributable. Useif: always()on each step so one failure doesn't hide the others. -
Linux
e2eande2e-full: apply the same packing to rows whose p90 test time is under 2 min. That is about 80% of the 117 rows. Target bins of about 6–8 min, which stays well under the Gradle legs (10–14 min) so the critical path doesn't grow. Generate the bins from a duration table checked intoscripts/(likeci-test-shard.py) rather than by hand. -
Keep the matrix row → suite mapping under test (
scripts/test_ci_*.py) so every suite/version combination still runs exactly once.
Expected saving
- macOS: about 19 fewer jobs × about 0.45 min fixed cost ≈ 8.5 macOS min per run. At 141 runs/day (merge_group, push and nightly), that is ~1,200 macOS job-min/day, or about 900/day if CI perf: CI on push to main re-tests the exact SHA the merge queue just passed (~16,000 job-min/day, ~1,800 macOS) #1170 removes the push re-run. macOS slots per run drop from 23 to 4.
- Linux: packing about 33,000 of the sub-2-min jobs a day roughly 4:1 removes about three quarters of their about 9,000 min/day of setup-step time, so ~6,000 Linux job-min/day. Runner provisioning, which these numbers don't count, comes on top. It also removes about 25,000 Linux job starts a day, which is the load behind the 5–10 min busy-hour queue waits.
- Critical path: neutral to slightly positive, from less queue wait for the Gradle legs.
Coverage and risk
- Every suite and tool-version still runs in the same events (PR / merge_group / push / nightly). Only the job grouping changes.
- Failure attribution gets coarser, which per-suite steps mitigate.
- A flaky suite now fails a bigger job. Re-runs cost more per failure, but there are fewer jobs.
- Required checks
ci-okandclippyare unchanged.ci-okkeepsneeds:on the same job ids.
Effort
L. It restructures the matrices and needs a generator script plus test updates.
ROI
ROI = weighted saving × confidence / effort. Weighted saving is (Linux 6.0 + 3 × macOS 1.2) k job-min/day = 9.6. Confidence is 0.6. Effort L counts as 3.
ROI = 9.6 × 0.6 / 3 = 1.9
Activity
mikolalysenko commentedon Oct 8, 2026
[agent] Shares root cause with #1176, #1178:
ci.ymlgives every suite × toolchain row of thee2e/e2e-macos/e2e-fullmatrices its own job, so per-job setup dominates sub-minute test legs. Will be fixed together. Triaged aspriority:p3(CI-only).Generated by Claude Code
mikolalysenko commentedon Oct 9, 2026
Profiler refresh, 2026-10-09 16:16 UTC. Sample: 31 successful merge_group runs and 23 full PR
CIruns since 12:24.e2e (ubuntu-latest, …)legs per runRun …steps (setup, checkout, artifact download), e2e + macOS jobsCIruns (103 success, 92 cancelled, 15 failed). At about 28 macOS job starts per run, that is roughly 5,000+ macOS job starts per day, counting partial starts in cancelled runs.Generated by Claude Code
mikolalysenko commentedon Oct 11, 2026
[agent] Re-verified against origin/main (578b63e) on 2026-10-11: the fan-out this issue measured is gone. The lean
e2ematrix is 16 Linux legs on Depot (ci.yml:1055-1270, down from ~106-118), multi-suite rows share one leg (e.g. composer, gem, maven rows), ande2e-macos/e2e-windows/e2e-extendedare full-scope only (ci.yml:1906, 1870, 1755). Merge-queue run https://github.com/SocketDev/socket-patch/actions/runs/38099894100 has 47 jobs in total including the skipped full-tier ones. Further leg-merging would save little now that Depot removes the queue wait. Closing as completed.Generated by Claude Code