Fast compiles
You change one line, you want to see it, and you wait. What you wait for is a
rebuild: Cargo compiling what changed and joining it to the rest, a job called
linking. It's the wait you'll meet a hundred times a day, so it's the one that
matters. A game made with shuyi new rebuilds in about a second, on the stable Rust it
pins:
A new grid game | Linux | Windows (MSVC) | Windows (GNU) |
|---|---|---|---|
Rebuild after a one-line change in main.rs | 0.7–1.0 s | 1.8–1.9 s | 1.1 s |
cargo check after the same change (what an editor runs) | 0.1 s | 0.2 s | 0.2 s |
| Clean build | 40–55 s | 105–120 s | 25 s |
A clean build compiles everything, the engine included, as your first build does.
cargo check looks for errors and doesn't make a program, which is why it's so quick.
MSVC and GNU are Rust's two toolchains on Windows
(chapter 1).
Linux and Windows (MSVC) are GitHub's 4-core runners; Windows (GNU) is a 24-core desktop. The engine's CI measures a new game's rebuild on every change to the engine, and fails one that goes over its budget.
The setup
You don't need to do anything for this: it comes with a new game. It is in the root
Cargo.toml, whose comments say the same, and you can read on if you want to change it.
- No debug info in
devbuilds (debug = false).devis the buildcargo runmakes, and debug info is the extra data a debugger reads. Leaving it out takes about a third off each rebuild. A panic still names its file and line; setdebug = "line-tables-only"for lines in backtraces, the list of what was running when it stopped, ortruefor a debugger. - The engine and every other crate built optimized (
opt-level = 2for"*"), so the game runs at speed in a debug build. They rarely change, so you pay for that once. Level 1 makes no rebuild faster. - The linker Rust picks. On Linux, Rust's own
rust-lldhas been the default since Rust 1.90, andmoldis no faster. On Windows with the GNU toolchain,rust-lldcan't read the import libraries a game links, so MSYS2's linker stays; with MSVC,rust-lldis no faster thanlink.exe. - Incremental builds of the game's own crates, cargo's default for
dev, which reuse what didn't change: without them a rebuild takes 10 to 50 % longer.
Linking the engine as one dynamic library, a file loaded when the program starts, as Bevy's
dynamic_linking does, made no rebuild faster: the engine's crates are few and already
built, so linking them statically, into the program, costs little.
When it's slow
- The first build takes minutes. That's the clean build, and it happens once per
folder, and again when you change the Rust version, or run
cargo clean. - A rebuild takes much longer than the table. See whether you added a dependency, which
has to compile too, and whether you changed
debugor anopt-level.cargo build --timingswrites a page saying where the time went. cargo run --releaseis slow to build. A release build is the one you ship: it optimizes everything, so it takes a lot longer. Use it for shipping, and for measuring speed.
On a nightly toolchain
Nightly is the Rust that's built each night, with features not yet finished. Two more
options may help, for a developer to try in their own .cargo/config.toml: the Cranelift
backend (-Zcodegen-backend=cranelift, with the rustc-codegen-cranelift component) and
shared generics (-Zshare-generics=y).