docs(build): record the thin-binary layout and its measured effect
Replace the 'known remaining inefficiency' section with the layout that now exists, plus the measured before/after (clean release build: 2m14s -> 1m46s wall, keydr units 61.0s -> 32.4s, peak ~2.0 GB unchanged). Add a maintenance note: new modules go in src/lib.rs, not src/main.rs. Re-declaring them in the binary would silently restore the double compile this refactor removed.
This commit is contained in:
+28
-24
@@ -9,8 +9,9 @@ cargo build --release
|
||||
```
|
||||
|
||||
Plain cargo. No wrapper, no memory ceiling, no reduced optimisation.
|
||||
A clean release build peaks at **1.92 GB** and takes **2m17s** on a
|
||||
4-core / 7.6 GB VM.
|
||||
A clean release build peaks at **~2.0 GB** and takes **1m46s** on a
|
||||
4-core / 7.6 GB VM; an incremental rebuild after touching one file is a
|
||||
few seconds.
|
||||
|
||||
If that's not what you're seeing, read on.
|
||||
|
||||
@@ -87,35 +88,38 @@ Nothing there reduces the optimisation of shipped code.
|
||||
|
||||
---
|
||||
|
||||
## Known remaining inefficiency
|
||||
## Project layout
|
||||
|
||||
`src/main.rs` re-declares the whole module tree (`mod app; mod config;
|
||||
...`) instead of depending on the `keydr` lib target, so **every module
|
||||
compiles twice** — once for the lib, once for the bin. The `i18n!` macro
|
||||
must therefore be invoked in both crate roots (`t!()` expands to
|
||||
`crate::_rust_i18n_t`, so it must exist in each crate).
|
||||
All application code lives in the **library** (`src/lib.rs` → `src/run.rs`
|
||||
and the module tree). `src/main.rs` is a 10-line entry point that calls
|
||||
`keydr::run()`.
|
||||
|
||||
Measured with `cargo build --release --timings` on a clean tree, the two
|
||||
duplicated units are the slowest in the whole graph:
|
||||
This matters for build time. `main.rs` used to re-declare the whole module
|
||||
tree (`mod app; mod config; ...`), which made the binary a *second
|
||||
independent crate*: every module — and the entire rust-i18n translation
|
||||
table — was compiled twice, and 281 unit tests ran twice.
|
||||
|
||||
Measured effect of consolidating it, clean release build:
|
||||
|
||||
```
|
||||
33.7s keydr (bin)
|
||||
26.0s keydr (lib)
|
||||
1.4s generate_test_profiles (bin)
|
||||
------
|
||||
61.0s of 292.2s total unit-seconds (21%)
|
||||
before after
|
||||
keydr (bin) 33.7s 0.3s
|
||||
keydr (lib) 26.0s 31.0s
|
||||
keydr total 61.0s 32.4s (-28.6s)
|
||||
total unit-seconds 292.2s 264.5s
|
||||
wall clock 2m14s 1m46s (-28s, -21%)
|
||||
```
|
||||
|
||||
So restructuring `main.rs` to `use keydr::...` would save roughly 26s of
|
||||
compile work — real, but nowhere near half the build. Wall-clock saving is
|
||||
smaller still, since those units partly overlap with dependency
|
||||
compilation across 3 parallel jobs (292s of unit-work compressed into
|
||||
~2m15s wall). Worth doing for code hygiene; not a build-performance
|
||||
emergency.
|
||||
Test coverage is unchanged — 341 unique tests before and after. The
|
||||
execution count dropping from 622 to 340 is the duplicate run disappearing.
|
||||
|
||||
Note the remaining ~79% is dependency compilation (`reqwest` 12.7s,
|
||||
`clap_builder` 11.4s, `toml_edit` 9.3s, `tokio` 8.0s...), which is
|
||||
one-time work that incremental builds skip entirely.
|
||||
**Keep it this way:** if you add a module, declare it in `src/lib.rs`, not
|
||||
`src/main.rs`. Re-declaring modules in the binary would silently restore
|
||||
the double compile.
|
||||
|
||||
The remaining ~79% of build time is dependency compilation (`reqwest`
|
||||
12.7s, `clap_builder` 11.4s, `toml_edit` 9.3s, `tokio` 8.0s...), which
|
||||
incremental builds skip entirely.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user