Skip to content

ci: reuse cached builds and packages instead of rebuilding them - #182

Merged
brndnmtthws merged 9 commits into
mainfrom
ci/faster-ci
Oct 23, 2026
Merged

brndnmtthws merged 9 commits into
mainfrom
ci/faster-ci

Conversation

@brndnmtthws

@brndnmtthws brndnmtthws commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Why CI was slow

Measured over the 10 CI runs before this change (median wall 591 s, range 451–1890 s):

  • apt mirror stalls. install-lavapipe.sh and install-cuda-headers.sh each ran apt-get update && install in every Linux job. The Azure Ubuntu mirror sometimes served at ~10–30 kB/s: the slowest runs spent 7 min on mesa-vulkan-drivers and 19 min on libclang-dev in one job (1880 s test job).
  • Rust jobs compiled the optional-feature dependencies on every run. mr-boxington-action's target payload prunes target/ to the packages cargo metadata lists for the default features. Every --all-features job therefore recompiled wgpu/naga, cuda-core/bindgen, and objc2 (54 of the 72 crates the x86_64 test job compiled).
  • XGBoost rebuilt from source on every parity run (~3.7 min). The uv cache key named no uv release. After the uv bump, the exact-hit entry held the old uv's cache buckets and never the new one's wheel, so the save was skipped every time.
  • The fuzz build was never cached. cargo-fuzz builds in fuzz/target, while the job cached the root target/ ("No reusable Cargo target state was produced").
  • Python wheel, sdist, and CUDA runtime builds had no compiler cache, and the CUDA runtime built with the release profile's LTO.

Changes

  • .github/actions/lavapipe: caches the lavapipe .debs per runner image (ImageOS/ImageVersion) and installs them with dpkg. Only a cache miss contacts the mirror.
  • install-cuda-headers.sh: no more apt. The runner images' clang already ships libclang, which bindgen loads. The manylinux container mode keeps dnf install clang-devel.
  • Rust jobs: github-cache-mode: objects (isolate-objects-cache, cache-links). mbx's objects cover every feature and target directory, plus linked build scripts and proc macros. Still saved only on pushes to main.
  • parity: the uv cache key includes the uv version.
  • fuzz: caches fuzz/target itself (MBX_TARGET_VIEWS=0, so it is a real directory). The entry is saved on main without hessboost's and the fuzz targets' outputs, which every crate change rebuilds.
  • Python wheels (Linux/macOS), the sdist round trip, and the CUDA runtime build with maturin through mise's cargo, so through mbx and its cache. The CUDA runtime also builds without release LTO, like the wheel jobs. UV_CACHE_DIR sits on the checkout's volume, so uv hard-links packages on Windows instead of copying them.
  • Windows wheels build with the toolchain's own cargo (pinned by mise), not through mbx. On Windows, mbx makes the libzstd C build in zstd-sys's build script erratically slow: 3–6 min instead of <1 min in 5 of 18 builds under mbx, with or without MBX_CC=0 / MBX_BUILD_SCRIPT_EXECUTION=0, and never in the 25 builds without it (20 baseline, 5 on this branch).
  • mise.lock gains windows-x64 entries, and mise.ci.toml's RUSTUP_HOME uses xdg_data_home, so Windows jobs get the pinned toolchain from the mise cache.

Timings

Baseline: the 10 runs before this PR. New: the final configuration's run (39901730653). It restored caches built at an earlier commit and rebuilt hessboost, as a typical PR does.

Job Baseline median (range), s New, s
Wall time 591 (451–1890) 443
Sum of job times (runner time) 5472 (4694–7999) 3449
test (aarch64-darwin) 500 (257–590) 433
test (x86_64-linux) 340 (270–1880) 284
test (aarch64-linux) 274 (235–465) 282
Python / windows-latest / abi3 350 (260–368) 335
XGBoost and LightGBM parity 344 (234–416) 124
fuzz (smoke) 286 (195–293) 221
Python / ubuntu-26.04 / CUDA runtime 291 (189–679) 153
Python / ubuntu-26.04 / abi3 246 (152–595) 132
Python / macos-latest / abi3 231 (124–332) 156
Python sdist round-trip 210 (150–222) 119
clippy (x86_64-linux) 118 (99–486) 62
MSRV (1.93.0) 112 (102–869) 51

A rerun without source changes (everything cacheable hits) took 293 s wall. The first run on main after merge is cold for the new cache generations, about the cost of the old setup. PRs restore main's entries after that.

Remaining critical path

test (aarch64-darwin) now bounds the wall time. It spends almost all of its time compiling hessboost itself: the library, its unit tests, 33 integration tests, and 30 examples on a 3-core runner. Across runs with identical work, its nextest step took 265–508 s, depending on the runner. Building examples in that job costs ~13% of the crate build (measured locally at -j3); clippy --all-targets already type-checks them. I left examples in the build, since dropping them would reduce coverage.

- Rust jobs: mr-boxington-action's `target` payload pruned the target
  tree to the packages `cargo metadata` lists for the default features,
  so every `--all-features` job recompiled the wgpu, CUDA, and Metal
  dependency trees (and their dependents) on every run. Cache mbx's
  objects instead, which cover every feature and target directory,
  with native links (build scripts, proc macros).
- fuzz: cargo-fuzz builds in fuzz/target, which the job never cached
  (it cached the root target/). Cache fuzz/'s own tree.
- parity: the uv cache key named no uv release, so after uv moved its
  cache buckets the exact-hit entry never held the built XGBoost wheel
  and every run rebuilt XGBoost from source. Key it on the uv release.
- lavapipe: cache the .deb files per runner image and install them with
  dpkg (.github/actions/lavapipe); the Ubuntu mirror stalled jobs for
  minutes. libclang comes from the runner images' clang, so the CUDA
  header script no longer installs libclang-dev with apt.
- Python wheels, the sdist round trip, and the CUDA runtime build with
  maturin through mise's cargo, so through mbx and its cache (the CUDA
  runtime without the release profile's LTO, as the wheel jobs).
  mise.lock gains windows-x64 entries for the Windows wheel jobs, and
  mise.ci.toml's RUSTUP_HOME follows mise's data directory there.
@brndnmtthws
brndnmtthws marked this pull request as ready for review October 23, 2026 05:03
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T11:42:38.164190Z b74723a New commits
🔒 Security Review ✅ Completed 2026-10-23T11:42:41.625174Z b74723a New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7f0da87563

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/actions/lavapipe/action.yml Outdated
# resolved on one install as is on every runner of that image.
- id: key
shell: bash
run: echo "key=lavapipe-${ImageOS:?}-${ImageVersion:?}-$(dpkg --print-architecture)" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Invalidate the lavapipe cache when its installer changes

Include the installer or a package-set generation in this key. If install-lavapipe.sh later adds or changes a package while ImageVersion remains constant, this restores the previous nonempty directory; the installer then sees an existing *.deb, skips downloading the revised package set, and the exact cache hit prevents replacement. That can leave the Vulkan dependencies incomplete and break the Linux GPU test paths this action is meant to enable.

AGENTS.md reference: AGENTS.md:L103-L106

Useful? React with 👍 / 👎.

@brndnmtthws
brndnmtthws merged commit 2a92a49 into main Oct 23, 2026
34 checks passed
@brndnmtthws
brndnmtthws deleted the ci/faster-ci branch October 23, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant