Cargo compile-time investigation
Research date: 2026-08-26.
Conclusion
Do not change the shared Cargo profiles now. First measure one cold build and
one warm rebuild. The most useful local experiment is less debug information
for the dev and test profiles. Keep the current hosted CI cache and job
limits. They already match the current CI decision.
The release profile is not a compile-time target. It uses full LTO and one code-generation unit for small release files. Cargo states that LTO adds link time, and rustc states that one code-generation unit can compile more slowly. This is an accepted size trade-off in ADR-0015.
Current state
Cargo.toml has no dev or test profile settings. Cargo therefore uses
incremental compilation, 256 code-generation units, and full debug information
for normal local builds. Tests inherit the dev profile. Incremental data is
stored under target/ and only applies to workspace members and path
dependencies. Cargo profiles
define these defaults.
Hosted CI sets CARGO_INCREMENTAL=0, limits the core Cargo chain to two jobs,
uses sccache, and caches only downloaded Cargo inputs. This implements
ADR-0108. Do not enable incremental
compilation in those jobs. The ADR records that it does not combine well with
the CI compiler-result cache.
The workspace already keeps the Docker performance test package outside the normal workspace. This avoids its dependency graph in normal workspace builds, as ADR-0108 requires.
Measurement plan
Use the same Rust toolchain, target directory, and command for each comparison.
Record an empty-target result and a result after one small edit in src/.
cargo build --timings
cargo test --workspace --timings
Cargo writes an HTML timing report with per-compilation duration and concurrency
data to target/cargo-timings. The report is for human use, not for machine
input. Cargo build timing reports
Run this baseline before each experiment:
cargo clean
cargo build --timings
# Change one small Rust implementation file.
cargo build --timings
Do not use cargo clean in the normal edit loop. It removes the incremental
data that Cargo reuses for warm rebuilds.
Ranked experiments
1. Use line tables for local debug builds
Test this root manifest setting in a separate branch:
[profile.dev]
debug = "line-tables-only"
[profile.dev.package."*"]
debug = false
[profile.debugging]
inherits = "dev"
debug = true
line-tables-only keeps file names and line numbers for workspace backtraces
but omits variable and parameter information. The dependency override omits
their debug information. Full debug information is the current default for
dev, so this can reduce compiler and linker work. The debugging profile is
an opt-in full-debug path. Cargo documents this exact pattern and its faster
code generation, faster linking, and smaller target directory trade-offs.
Cargo build performance guide
Accept this only if the measured cold and warm times improve and the reduced debugging detail is acceptable. This project uses Rust 1.97.1, so the setting is available.
2. Use the local sccache cache for cold rebuilds
CI already uses sccache. A developer can also set RUSTC_WRAPPER=sccache in
a personal Cargo configuration. Cargo supports a rustc-wrapper command and
the RUSTC_WRAPPER environment variable. Cargo build wrapper
configuration
Keep this as local setup, not a repository requirement. The sccache local cache is 10 GB by default and only supports one server at a time. Concurrent servers can cause build failures. sccache local cache rules
Measure a clean rebuild after a branch switch. Do not expect a large gain for one-file warm rebuilds. Cargo incremental compilation already targets that case.
3. Build the smallest relevant package set
The workspace includes the CLI, the Wasm helper, and the performance harness. Use the CLI package for an ordinary CLI edit:
cargo test --package criv
Use cargo test --workspace before a shared-crate, manifest, or release change.
Cargo supports explicit package selection, so the smaller command does not
build unrelated workspace members. Cargo package
selection
4. Do not reduce code-generation units before measurement
The default incremental value is already 256. More units allow more parallel code generation and can reduce compile time, but can make generated code slower. One unit can improve generated code but can compile more slowly. Cargo code-generation units rustc code-generation units
Do not change this value for dev or test unless the timing report shows a
clear CPU-parallelism limit. Do not change the release value. ADR-0015 owns its
size result.
Rejected changes
- Do not add LTO to
devortest. Cargo states that LTO increases link time. - Do not increase
opt-levelto make compilation faster. Higher optimization levels can increase compiler time. Cargo optimization levels - Do not enable Cargo incremental compilation in hosted CI. ADR-0108 owns the
selected
sccachestrategy. - Do not cache the full
target/directory in CI. ADR-0108 rejects this due to cache size and transfer time.
Decision trigger
Create an ADR before changing Cargo.toml, hk.pkl, or the hosted workflow.
ADR-0015 governs the release profile. ADR-0108 governs CI compilation and
caching. A local-only developer guide can change without a new ADR if it does
not change those shared settings.