Repository navigation
perf(release): add PGO builds for natively-trainable release targets - #11031
Conversation
Ports jdx/aube's three-phase rustc PGO pipeline to mise: build with -Cprofile-generate, train, rebuild with -Cprofile-use. The training workload is hermetic and offline — throwaway HOME with isolated MISE_*_DIRs exercising the startup-dominated hot paths: settings and config load, toolset resolution, hook-env (full run and the per-prompt early-exit fast path), env rendering, task listing, and exec. Enabled for the targets whose instrumented binaries can execute on their build runner: x86_64 linux gnu/musl (cross-built, trained on the amd64 host) and native macos-arm64. arm/armv7 Linux, macos-x64, and Windows keep plain serious builds. Measured on macOS arm64 against a same-source serious build (hyperfine -N, warm, isolated env): - mise version: 4.3ms -> 4.1ms - mise current: 6.9ms -> 6.3ms (1.10x) - hook-env early-exit fast path (per shell prompt): 3.6ms -> 3.3ms - binary size: 84.5MB -> 81.3MB; startup pages touched: 1182 -> 1079 Costs one extra serious-profile build per PGO target, so the linux tarball job budget goes from 45 to 80 minutes. Backing a target out is deleting its `pgo: 1` matrix line. Cross.toml now passes RUSTFLAGS through so the profile-generate/-use flags reach cargo inside cross containers, and pgo.bash bind-mounts the profile dir at the same path so -Cprofile-use resolves there. BOLT post-link optimization (Linux-only, layered on PGO) is a potential follow-up; aube's phase-4 flow is the template. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughRelease tarball workflows now enable PGO for selected Linux and macOS targets. The tarball script invokes a new three-phase PGO process, while Cross configuration scopes host ChangesProfile-guided release builds
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant ReleaseWorkflow
participant build_tarball
participant pgo_bash
participant mise
participant llvm_profdata
ReleaseWorkflow->>build_tarball: Set MISE_PGO and install LLVM tools
build_tarball->>pgo_bash: Pass target and build features
pgo_bash->>mise: Build instrumented binary
pgo_bash->>mise: Run offline training workload
mise-->>pgo_bash: Write profraw files
pgo_bash->>llvm_profdata: Merge profiles
pgo_bash->>mise: Rebuild with profile-use flags
Suggested labels: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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 |
Greptile SummaryThis PR wires a three-phase profile-guided optimization (PGO) pipeline into the release tarball builds for
Confidence Score: 5/5Safe to merge; the PGO pipeline is well-guarded and failures are loud, not silent. The implementation is careful and well-validated: profraw count check, merged-profile existence check, per-target RUSTFLAGS scoping, and hermetic training workload with isolated state dirs. The only finding is that pgo.bash hardcodes $REPO_ROOT/target/ without checking CARGO_TARGET_DIR, which has no effect in CI where that variable is unset. No files require special attention. scripts/pgo.bash is the most complex new file and is worth a read, but it is well-commented and carries over proven guards from aube's pipeline. Important Files Changed
Reviews (2): Last reviewed commit: "perf(release): scope RUSTFLAGS passthrou..." | Re-trigger Greptile |
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.7.7 x -- echo |
25.5 ± 1.4 | 21.4 | 29.7 | 1.00 |
mise x -- echo |
25.6 ± 2.6 | 19.7 | 66.6 | 1.01 ± 0.12 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.7.7 env |
24.9 ± 1.5 | 21.0 | 29.6 | 1.05 ± 0.09 |
mise env |
23.8 ± 1.6 | 18.7 | 29.0 | 1.00 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.7.7 hook-env |
26.3 ± 1.5 | 21.6 | 30.3 | 1.05 ± 0.10 |
mise hook-env |
25.0 ± 1.7 | 19.5 | 30.1 | 1.00 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.7.7 ls |
22.6 ± 1.4 | 17.7 | 27.9 | 1.06 ± 0.10 |
mise ls |
21.3 ± 1.6 | 16.8 | 26.6 | 1.00 |
xtasks/test/perf
| Command | mise-2026.7.7 | mise | Variance |
|---|---|---|---|
| install (cached) | 194ms | 194ms | +0% |
| ls (cached) | 77ms | 74ms | +4% |
| bin-paths (cached) | 83ms | 79ms | +5% |
| task-ls (cached) | 160ms | 157ms | +1% |
Review feedback: global [build.env] passthrough would silently inject host RUSTFLAGS into every cross build, including non-PGO arm targets. Scope it to the two x86_64 targets that PGO actually builds through cross. Also alias the phase-3b output as PGO_FINAL_BIN so the success log doesn't misleadingly reference the instrumented binary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 005258e. Configure here.
| RUSTFLAGS="${RUSTFLAGS:-} -Cprofile-generate=$PGO_PROFRAW_DIR" \ | ||
| "$PGO_BUILD_TOOL" build --profile="$PGO_PROFILE" $target_arg --bin mise "$@" | ||
|
|
||
| INSTRUMENTED_BIN="$REPO_ROOT/target/${target_dir_part}${PGO_PROFILE}/mise" |
There was a problem hiding this comment.
Ignores CARGO_TARGET_DIR for binary
Low Severity
scripts/pgo.bash always resolves the instrumented binary under REPO_ROOT/target/…, while cargo/cross honor CARGO_TARGET_DIR and scripts/build-tarball.sh packages from that same variable. With a non-default CARGO_TARGET_DIR, phase 1 can build in one tree while training checks or runs a binary from another, including a stale target/…/mise left from an earlier build.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 005258e. Configure here.


Summary
Ports jdx/aube's
benchmarks/pgo.bashthree-phase PGO pipeline to mise, wired into the release tarball builds. Follow-up to #11025 / #11027 / #11029 — this attacks the remaining first-touch page-in cost with profile-guided code layout, the last lever identified in that series.scripts/pgo.bash— instrument (-Cprofile-generate) → train → rebuild (-Cprofile-use). Training is hermetic and offline: throwaway HOME + isolatedMISE_*_DIRs exercising settings/config load, toolset resolution,hook-env(full and per-prompt early-exit fast path), env rendering, tasks, and exec. No registry infrastructure needed, unlike aube's Verdaccio workload. Carries over aube's hard-won guards: profraw sanity check, llvm-profdata silent-no-op check,LLVM_PROFILE_FILEoverride and profile-dir bind-mount for cross's container path translation.scripts/build-tarball.sh—MISE_PGO=1routes through pgo.bash with the identical feature set/profile; output lands at the same path.release.yml—pgo: 1on the targets whose instrumented binaries can execute on their build runner:linux-x64(gnu+musl, cross-built, trained on the amd64 host) andmacos-arm64(native). arm/armv7 Linux can't run their binaries on the runner, macos-x64 would train skewed under Rosetta (aube's precedent), Windows PGO is untested — all stay plainserious.Cross.toml— passRUSTFLAGSthrough to the container (without this, the PGO flags silently never reach cargo — aube hit exactly this).Measured effect (macOS arm64, same-source A/B, serious profile, hyperfine -N, warm)
mise versionmise currentHonest framing: 6–10% on the hot paths, not a silver bullet. For context, the whole series has taken
mise versionon this machine from 8.1 ms → 4.1 ms. Linux is unvalidated (no local toolchain on the test box) but expected to be in the same range; the bigger Linux win is BOLT, which layers on top of this and is the natural follow-up (aube's phase 4 is the template,bolt-19runner dependency, Linux GNU only — BOLT's instrumentation runtime SIGSEGVs on musl per aube's notes).Cost & rollback
pgo: 1matrix line.Verification
mise run lintclean (actionlint, shellcheck, shfmt)🤖 Generated with Claude Code
Note
Medium Risk
Changes how primary release binaries are compiled for key platforms; PGO failures fail the build with no silent fallback, and the cross+PGO path is less validated locally than native macOS.
Overview
Adds profile-guided optimization (PGO) to release tarballs for targets where the instrumented binary can be trained on the CI runner.
scripts/pgo.bashimplements a three-phase flow: instrument with-Cprofile-generate, run a hermetic offline workload (startup paths includinghook-envfast path), merge profiles withllvm-profdata, then rebuild with-Cprofile-use. It includes cross-container bind-mounts for profile paths,LLVM_PROFILE_FILEoverrides, and hard failures when no.profrawis produced.scripts/build-tarball.shroutes throughpgo.bashwhenMISE_PGOis set (usingcrosson Linux), leaving the sameseriousoutput path as before.release.ymlenables PGO forlinux-x64(gnu + musl) andmacos-arm64, installsllvm-toolson those matrix rows, passesMISE_PGO, and raises Linux job/retry timeouts (~45→80/75 min) for the extra build phase.Cross.tomlpassthroughsRUSTFLAGSonly for the x86_64 Linux gnu/musl targets so PGO flags reach cargo inside cross containers.Other Linux arch targets, macOS x64 (Rosetta skew), and Windows stay on plain
seriousbuilds.Reviewed by Cursor Bugbot for commit 005258e. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
New Features
Bug Fixes