Repository navigation
Conversation
v2.9.3 fixes the cleanup that runs after a partial cache restore. It returned after the first directory entry, so artifacts older than a week were kept and saved again in the next cache entry. See Swatinem/rust-cache#375. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
sccache stores one GitHub Actions cache entry per compiled crate. Jobs hit the cache service rate limits (HTTP 429 and 503), which turned cache reads into slow misses. Its many small entries also share the 10 GB repository cache quota with the rust-cache entries and push them out. rust-cache restores whole target directories with one request per job, so it covers the same dependency builds. Later commits extend it to the jobs sccache served alone: fuzzing, the non-PIE guests and the benchmark baseline. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Coverage and RustNightly run on a schedule. RustNightly saved its Rust and sysroot caches on every run. Their entries serve only the next scheduled run, yet count against the 10 GB repository quota and evict the entries pull requests restore. Both jobs now build without a cache. Miri saved its cache only from DailyArm64, under the arm64 key. Pull requests run Miri on X64, so they never restored that entry. Miri now only restores. Priming the X64 Miri cache is left to a follow-up. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
setup-rust-toolchain enables rust-cache by default. Copilot code review runs these steps on pull request branches and saves an entry of about 100 MB per branch, such as v0-rust-copilot-pull-request-reviewer-Linux-x64-aea9c2a7-2b9f5a70. Branch entries serve only that branch and evict the main entries every pull request restores. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
build-rust-guests-non-pie ran cargo hyperlight in target-non-pie to make a sysroot. That also built simpleguest a second time, about 12 s per job. The non-PIE build then compiled into target-non-pie/build, which rust-cache did not cover, about 11 s more. sccache served these builds. The non-PIE build now depends on build-rust-guests and uses its sysroot in target/sysroot. The toolchain and target are identical, so the sysroot is identical. rust-cache covers target-non-pie/build, and the sysroot cache holds only target/sysroot. The guests job builds nothing in the root workspace, so its target entry is dropped. Its lockfile no longer invalidates the guest cache either. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
bench-against builds the baseline commit in a worktree under target/baseline-worktree. Its target directory is empty in CI, so every pull request compiled the baseline from scratch. sccache served those builds. cargo ci bench takes --baseline-target-dir, passed to the baseline build as --target-dir. The benchmarks job copies the restored rust cache to a separate directory and passes it. A copy is needed because cargo fingerprints path packages by workspace path and mtime, so two checkouts cannot share one target directory. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
PrimeCaches built only the host library. Pull request jobs then compiled every test binary, dev-dependency and hyperlight-ci on top of the restored cache, and rust-cache never saved those from a pull request. just prime-caches builds what just test compiles and what cargo ci needs. It sets the cargo runner for the host target to a command that exits 0, so every test binary builds and none runs. Doctests are left out because rustdoc compiles them only when they run. Measured locally, a debug entry grows to 390 MB compressed and a release entry to 330 MB. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Every reusable workflow saved its rust-cache entry whenever it ran on main. Scheduled jobs such as DailyArm64, Fuzzing and DailyBenchmarks raced PrimeCaches for the same keys. Each writer built on a restored entry, and rust-cache keeps every dependency version it restores, so entries grew with each lockfile change. Code checks reached 1.7 GB against 676 MB for a clean build. PrimeCaches is the only writer. Its jobs look up their entry with lookup-only. On an exact hit they skip the build. Otherwise they build from a cold target and save, so an entry holds only what one lockfile needs. dep_build_guests and dep_code_checks take a prime_cache input for this. Priming skips C guests and uploads. cache-on-failure is dropped, so a failed build never saves a partial entry under the exact key. PrimeCaches runs queue so the newest commit always saves. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
ludfjig
marked this pull request as ready for review
October 21, 2026 01:37
ludfjig
requested review from
andreiltd,
danbugs,
dblnz,
devigned,
jprendes,
jsturtevant,
simongdavies,
squillace and
syntactically
as code owners
October 21, 2026 01:37
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Cache cleanup and fuzz priming have unresolved issues that undermine cache freshness and quota control.
3 open issues
What changed in this PR
Centralizes Rust cache writes in PrimeCaches to limit cache growth and avoid sccache rate limits.
Changes:
- Adds cold cache priming and superseded-entry cleanup.
- Removes sccache and makes other cache consumers restore-only.
- Adds benchmark baseline target reuse and fuzz build priming.
| File | Description |
|---|---|
| src/hyperlight_ci/src/bench.rs | Supports a separate baseline target directory. |
| Justfile | Adds priming recipes and shares the guest sysroot. |
| .github/workflows/RustNightly.yml | Removes nightly caching and sccache. |
| .github/workflows/PrimeCaches.yml | Coordinates priming and cache cleanup. |
| .github/workflows/dep_run_examples.yml | Restores versioned caches without sccache. |
| .github/workflows/dep_miri.yml | Makes Miri caches restore-only. |
| .github/workflows/dep_fuzzing.yml | Adds fuzz cache priming. |
| .github/workflows/dep_code_checks.yml | Restricts cache writes to priming. |
| .github/workflows/dep_build_test.yml | Restores host caches without writing. |
| .github/workflows/dep_build_guests.yml | Adds guest priming and non-PIE caching. |
| .github/workflows/dep_benchmarks.yml | Seeds the baseline target from restored artifacts. |
| .github/workflows/Coverage.yml | Removes coverage caching and sccache. |
| .github/workflows/copilot-setup-steps.yml | Disables toolchain caching. |
| .github/actions/setup-sccache/action.yml | Deletes the sccache setup action. |
Review effort: Balanced
| gh cache list --ref "$GITHUB_REF" --key "$prefix" --limit 1000 --json id,key,createdAt | ||
| done | jq -s -r ' | ||
| add | ||
| | group_by(.key | sub("-[^-]*$"; "")) |
| uses: ./.github/actions/setup-sccache | ||
| # One entry serves every target. Priming builds cold, so the entry holds | ||
| # only what this commit needs. | ||
| - name: Rust cache |
|
|
||
| # Builds every fuzz target with the flags `just fuzz` uses | ||
| build-fuzz-targets: | ||
| for t in $(cargo +{{nightly-toolchain}} fuzz list); do case "$t" in *trace*) f="--features trace" ;; *) f="" ;; esac; cargo +{{nightly-toolchain}} fuzz build "$t" --release $f || exit 1; done |
PR fuzz jobs compiled every fuzz target with sccache. With sccache removed they need a Rust cache. PrimeCaches builds every fuzz target from a cold target and saves one entry under the key fuzz-X64. Trace targets build with the trace feature, matching `just fuzz`. PR and scheduled fuzz jobs only restore it. The fuzz workflow installs the pinned nightly before the cache step. rust-cache hashes installed toolchains, so a pin change changes the key and triggers a new prime. The new `just build-fuzz-targets` recipe builds each target alone because the trace targets do not compile without the trace feature. It fails if `cargo fuzz list` fails or lists nothing, so an empty build is never cached. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Rust cache keys end in a toolchain hash and a lockfile hash. Sysroot keys end in one hash. Every dependency or toolchain update leaves the old entry on main until GitHub evicts it after seven days unused. Those entries count toward the 10 GB repository quota and push out current ones. A final PrimeCaches job keeps the newest entry for each key without its hashes and deletes the rest. It runs even if a prime job fails, which keeps the old entry for that job's key. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
The v0-rust entries on main grew over many builds on restored caches. PrimeCaches skips the build on an exact key match, so it would keep those entries until the next lockfile change. Every rust-cache step uses the prefix v1-rust. The first PrimeCaches run builds every entry from a cold target. The old v0-rust entries expire after seven days unused. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
ludfjig
force-pushed
the
ci-cache-priming
branch
from
October 21, 2026 03:14
59be1d4 to
13a312b
Compare
Benchmark ResultsMeasured commit: kvm / amd (Linux) (➖ stable)No benchmark improved or regressed. Benchmark Resultsfunction_call_codec
payload_allocation
sandboxes
slot_pool
snapshot_files
virtq_readonly
virtq_readwrite
kvm / intel (Linux) (➖ stable)No benchmark improved or regressed. Benchmark Resultsfunction_call_codec
payload_allocation
sandboxes
slot_pool
snapshot_files
virtq_readonly
virtq_readwrite
mshv3 / amd (Linux) (➖ stable)No benchmark improved or regressed. Benchmark Resultsfunction_call_codec
payload_allocation
sandboxes
slot_pool
snapshot_files
virtq_readonly
virtq_readwrite
mshv3 / intel (Linux) (➖ stable)No benchmark improved or regressed. Benchmark Resultsfunction_call_codec
payload_allocation
sandboxes
slot_pool
snapshot_files
virtq_readonly
virtq_readwrite
hyperv-ws2025 / amd (Windows) (➖ stable)No benchmark improved or regressed. Benchmark Resultsfunction_call_codec
payload_allocation
sandboxes
slot_pool
snapshot_files
virtq_readonly
virtq_readwrite
hyperv-ws2025 / intel (Windows) (➖ stable)No benchmark improved or regressed. Benchmark Resultsfunction_call_codec
payload_allocation
sandboxes
slot_pool
snapshot_files
virtq_readonly
virtq_readwrite
Reported by |
This branch has not been deployed
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.

Makes PrimeCaches the only workflow that writes Rust caches, and removes sccache.
PR CI hit sccache rate limits (429/503), and caches on main kept growing until they filled the 10 GB repository quota. rust-cache keeps every dependency version it restores, so entries saved after builds on restored caches grow with each lockfile change.
v1-rust-*andsysroot-*entries on main.v1-rustprefix, so the first run replaces the grownv0-rustentries.A cold PrimeCaches run on this branch saved about 8.6 GB in total. The largest entries are code-checks (1.4 GB Linux, 1.0 GB Windows) and the eight host entries (540–620 MB each).
Follow-ups: caches for Miri X64, Windows arm64, macOS and trace fuzz guests.
Easiest to review commit-by-commit