perf(build): upgrade rust-i18n v3 -> v4 to fix codegen blowup
Release builds consumed 5+ GB and never completed on a 4-core / 7.6 GB
VM, thrashing the machine badly enough to lose SSH access.
Root cause was a codegen bug in rust-i18n v3, not machine size. Its
macro emitted one HashMap::from([...]) and one add_translations() call
per translation string, all in a single function body -- 8,652 of each
for our 21 locales / ~9,000 keys. LLVM scales superlinearly on function
size, so optimising that one initialiser took ~4.5 GB.
Verified via cargo expand (lib target):
v3.1.5 v4.2.1
HashMap::from 8,652 0
add_translations 8,652 21 (one per locale)
expanded lines 93,026 73,444
Fixed upstream in v4.0.0.
Clean release builds, same machine:
v3, opt-level=3, thin LTO 5.2 GB stalled >18m, never finished
v3, opt-level=1, no LTO 1.8 GB 15m30s (previous workaround)
v4, opt-level=3, thin LTO 2.08 GB 3m25s
v4, stock cargo defaults 1.92 GB 2m17s
Also:
- Remove the opt-level=1 / lto=false workaround; cargo's release
defaults are correct now. No shipped code is de-optimised.
- Keep only genuine small-machine hygiene in .cargo/config.toml:
jobs=3 (keeps the box interactive), lld linker, and trimmed debug
info on dev/test profiles.
- Document the diagnosis, the cargo expand / llvm-lines workflow that
found it, and the systemd-based safety nets in docs/BUILDING.md.
- Note in main.rs why i18n! must appear in both crate roots (t! expands
to crate::_rust_i18n_t, and main.rs re-declares the module tree
rather than depending on the lib target).
Test suite passes; release binary verified working.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# Build configuration for keydr.
|
||||
#
|
||||
# HISTORY: this file once contained aggressive workarounds (LTO disabled,
|
||||
# opt-level dropped to 1) because release builds consumed 5+ GB and never
|
||||
# finished on a 4-core / 7.6 GB VM. That was NOT a hardware limitation —
|
||||
# it was a codegen bug in rust-i18n v3, fixed by upgrading to v4.
|
||||
#
|
||||
# With rust-i18n v4 the same machine does a full opt-level=3 + thin-LTO
|
||||
# release build with a 2.08 GB peak in 3m25s. See docs/BUILDING.md.
|
||||
#
|
||||
# What remains here is ordinary small-machine hygiene, not a handicap:
|
||||
# nothing below reduces the optimisation level of shipped code.
|
||||
|
||||
[build]
|
||||
# Cap parallelism at 3 of 4 cores. This is about keeping the machine
|
||||
# interactive (SSH stays responsive during a build), not about memory.
|
||||
# Remove it if you don't care about using the box while it compiles.
|
||||
jobs = 3
|
||||
|
||||
rustflags = [
|
||||
# Use the lld that ships with the Rust toolchain. GNU ld is
|
||||
# single-threaded and holds the whole link graph in memory; lld is
|
||||
# faster and leaner. The -B flag is the stable-Rust way to select it
|
||||
# (`-Clink-self-contained=+linker` requires nightly).
|
||||
#
|
||||
# If you move this repo to another machine, update this path or
|
||||
# install system lld and use plain `-fuse-ld=lld`.
|
||||
"-Clink-arg=-fuse-ld=lld",
|
||||
"-Clink-arg=-B/home/thallada/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld",
|
||||
]
|
||||
|
||||
[profile.dev]
|
||||
# Default is debug = 2 (full debug info), the dominant contributor to both
|
||||
# rustc peak memory and target/ size. Level 1 keeps line numbers, so
|
||||
# backtraces and panics still point at real source lines; you only lose
|
||||
# full variable inspection in a debugger.
|
||||
debug = 1
|
||||
split-debuginfo = "unpacked"
|
||||
|
||||
[profile.dev.package."*"]
|
||||
# Dependencies are compiled once and rarely stepped through in a debugger.
|
||||
# Dropping their debug info shrinks target/ and speeds up linking.
|
||||
debug = 0
|
||||
|
||||
[profile.test]
|
||||
debug = 1
|
||||
split-debuginfo = "unpacked"
|
||||
|
||||
[profile.test.package."*"]
|
||||
debug = 0
|
||||
|
||||
# NOTE: [profile.release] is deliberately absent — cargo's defaults
|
||||
# (opt-level = 3, codegen-units = 16, no LTO) are correct for this project
|
||||
# now. Add `lto = "thin"` if you want it; measured at 2.08 GB peak / 3m25s
|
||||
# on this box, which is comfortable.
|
||||
Reference in New Issue
Block a user