From fc1fee00cb7463996fe24df52328e3878b8353d8 Mon Sep 17 00:00:00 2001 From: Robert M1 <50460704+githubrobbi@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:49:27 -0700 Subject: [PATCH 1/2] =?UTF-8?q?perf(build):=20add=20`ship`=20profile=20(bu?= =?UTF-8?q?ild-std=20+=20immediate-abort)=20=E2=80=94=20drops=20backtrace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Field binaries are stripped, so a *symbolized* panic backtrace is dead weight: the gimli/addr2line DWARF machinery inside std is ~10% of the CLI. Add a dedicated `[profile.ship]` (inherits `release`, `panic = "immediate-abort"`), built with `-Z build-std`, so a field panic is a bare, process-local `abort()` (no message, no backtrace) — matching the workspace no-panic lint policy. Dev + CI keep normal panics + full backtraces. Measured (x86_64-pc-windows-msvc, uffs.exe): 1,292,800 -> 1,167,872 (-9.7%), and it applies to every shipped binary. Deliberately NOT wired into the default release — build-std is unstable + rebuilds std; opt in from the ship build when ready. Normal dev/release/clippy builds are unaffected (used only with `--profile ship -Z build-std`). --- Cargo.toml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 6a025942b..f493b9d5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,7 @@ +cargo-features = [ + "panic-immediate-abort", +] # ship profile only (needs -Z build-std) + # ============================================================================= # Cargo.toml - UFFS (Ultra Fast File Search) Workspace # ============================================================================= @@ -763,6 +767,34 @@ opt-level = 0 [profile.release.package.uffs-cli] opt-level = "z" +# ───────────────────────────────────────────────────────────────────────────── +# Ship profile — minimal panic (removes the field-useless backtrace machinery) +# ───────────────────────────────────────────────────────────────────────────── +# Field binaries are stripped, so a *symbolized* backtrace is dead weight — the +# `gimli`/`addr2line` DWARF machinery inside std is ~10% of the CLI. This profile +# rebuilds std with `panic = "immediate-abort"`, so a field panic is a bare, +# process-local `abort()` (no message, no backtrace) — which matches the +# workspace no-panic lint policy (panics are forbidden in prod anyway). Dev + CI +# keep normal panics + full backtraces. +# +# Built ONLY with build-std (needs nightly + the `rust-src` component): +# cargo [xwin] build --profile ship -Z build-std=std,panic_abort --target +# +# Measured (x86_64-pc-windows-msvc, uffs.exe): 1,292,800 → 1,167,872 (−9.7%). +# +# CAVEAT: `panic_immediate_abort` became a first-class panic strategy in recent +# nightlies (it was a `-Z build-std-features` flag before), so this is unstable +# and may need re-touching on a toolchain bump. Deliberately NOT wired into the +# default release — opt in from the ship build when ready to own that. +[profile.ship] +inherits = "release" +panic = "immediate-abort" + +# Per-package overrides do not inherit into a derived profile, so keep the CLI +# size-first here too. +[profile.ship.package.uffs-cli] +opt-level = "z" + # ───────────────────────────────────────────────────────────────────────────── # Cross-compile profile for cargo-xwin (macOS → Windows MSVC) # ───────────────────────────────────────────────────────────────────────────── From 47ea70c08182d3f9b4202694e46da832461b8520 Mon Sep 17 00:00:00 2001 From: Robert M1 <50460704+githubrobbi@users.noreply.github.com> Date: Wed, 8 Jul 2026 20:51:15 -0700 Subject: [PATCH 2/2] ci(release): Windows binaries ship with panic=immediate-abort (build-std) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wire the `ship` profile into the release build for the WINDOWS target only: rebuild std with `panic=immediate-abort` + `optimize_for_size` via `-Z build-std`, so shipped Windows binaries drop the field-useless backtrace machinery (~10% off the CLI: uffs.exe 1,292,800 -> 1,167,872). Linux/macOS stay on `--release`. The `ship` profile outputs to target//ship/; mirror the built .exe files into release/ so the packaging steps need no path changes. Windows builds natively on windows-latest with the pinned nightly + rust-src (both from rust-toolchain.toml), so build-std resolves. CAVEATS (validate with a pre-release tag before a real ship): build-std is unstable (panic_immediate_abort changed shape across a recent nightly) and rebuilds std, so watch the 75-min Windows timeout on a cold cache; `optimize_for_size` was not measured locally (only `build-std=std,panic_abort` was, at -9.7%) — a test release will confirm both. --- .github/workflows/release.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e4d4c6666..7a70448e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -530,6 +530,26 @@ jobs: # → the native cargo build. Same flags/profile either way. if [[ "${{ matrix.target }}" == *musl* ]]; then cargo zigbuild --locked --release --target ${{ matrix.target }} --workspace --bins + elif [[ "${{ matrix.target }}" == *windows* ]]; then + # Windows-ONLY size strip: rebuild std with panic=immediate-abort + + # size-optimized std, so a field panic is a bare, process-local + # abort() with no backtrace. The gimli/addr2line DWARF machinery is + # ~10% of the CLI and useless on a stripped binary; a panic is a + # should-never-happen bug (the workspace lints forbid unwrap/panic + # in prod), so dropping the diagnostic is the right trade for ship. + # Needs nightly + rust-src (both from rust-toolchain.toml). Linux and + # macOS deliberately stay on the plain release profile. Measured: + # uffs.exe 1,292,800 -> 1,167,872 (-9.7%). See [profile.ship] in + # Cargo.toml. + cargo build --locked --profile ship \ + -Z build-std=std,panic_abort \ + -Z build-std-features=optimize_for_size \ + --target ${{ matrix.target }} --workspace --bins + # The `ship` profile outputs to target//ship/, but every + # packaging step below reads target//release/ — mirror the + # built .exe files across so none of those paths need to change. + mkdir -p "target/${{ matrix.target }}/release" + cp "target/${{ matrix.target }}/ship/"*.exe "target/${{ matrix.target }}/release/" else cargo build --locked --release --target ${{ matrix.target }} --workspace --bins fi