fix(build): use thin LTO to cut peak build memory#367
Conversation
|
Binary size comparison now measured (aarch64-apple-darwin, release,
So this costs +3.6 MB, +18%. That is not nothing, and it is the honest trade: a somewhat larger binary in exchange for If the size regression is unacceptable, the middle option is Worth noting the size question mostly affects people downloading release binaries, who are unaffected by the build-memory problem either way. |
|
I recommend you to check this https://github.com/johnthagen/min-sized-rust |
Fat LTO with codegen-units = 1 is the highest-peak-memory codegen configuration available, and applying it across a ~400 crate graph needs a multi-GB heap at link time. On low-memory ARM boards this OOMs, and because cargo install writes its target dir into /tmp -- which Armbian mounts on zram, sized to RAM/2 -- the resulting truncated rlib surfaces as 'failed to load bitcode of module'. Thin LTO keeps most of the optimisation benefit without the fat LTO memory cliff, and dropping codegen-units = 1 restores codegen parallelism. Refs #366
2274813 to
485bd96
Compare
|
Closing: we are keeping fat LTO. The +18% binary size (19.6 → 23.2 MB) is not worth paying on every release download to fix a problem that only affects people compiling from source on memory-constrained machines — and those people now have a documented escape hatch. #368 (merged) tells them to keep the build off the RAM-backed CARGO_TARGET_DIR=~/.cache/cookcli-build cargo install cookcli --lockedand, if memory is still tight, to turn off LTO for their own build: CARGO_PROFILE_RELEASE_LTO=false CARGO_TARGET_DIR=~/.cache/cookcli-build cargo install cookcli --lockedThe better answer for SBC users remains the prebuilt The diagnosis in this PR still stands and is worth keeping on record: the error in #366 is only reachable through the fat-LTO path, and it fires because |
Fixes the
cargo installfailure reported in #366.Problem
That message is emitted from exactly one place in rustc — the fat LTO path (
run_fatinrustc_codegen_llvm/src/back/lto.rs). We opt into it ourselves:Fat LTO with
codegen-units = 1is the highest-peak-memory codegen configuration available, and we apply it across a ~400 crate graph. Note the reporter's error ends with":and an empty LLVM message — LLVM was handed a buffer that is not valid bitcode (a truncated.rlib), rather than hitting a codegen bug, which would print a concrete diagnostic likeInvalid cast.The truncation has a clear source on their platform:
cargo installwrites its target dir under$TMPDIR(hence/tmp/cargo-installwdiPPp), and Armbian mounts/tmpon zram — RAM-backed, sized to RAM/2 by default (armbian-zram-config). So 1.3 GB of build artifacts land in RAM on a board that simultaneously needs a multi-GB heap for fat LTO.Change
lto = "thin", and drop thecodegen-units = 1pin (back to the release default of 16). Thin LTO keeps most of the cross-crate optimisation benefit without the fat-LTO memory cliff, and restores codegen parallelism.Verification
Release build succeeds; resulting binary is 23 MB on aarch64-apple-darwin. I did not complete a clean fat-LTO size comparison locally, so if binary size is a hard constraint here, worth checking CI's artifact sizes before merging — some size regression is expected and is the intended trade for not OOMing on a 1–2 GB SBC.
Refs #366