Build time is the tax you pay on every idea. It sets how many things you try before lunch, whether you check a hunch or talk yourself out of it, and how long a bisect takes. It is the goal that sounds softest and compounds hardest, so it is worth measuring rather than asserting.
The measurement
C++ OrbitService | Rust orbit-service | |
|---|---|---|
| cold build | 148.5 s | 10.7 s |
| work units | 4,506 Bazel actions | 116 crates |
| incremental (one file) | — | 5.0 s |
| build tool | Bazel | cargo |
Both on the same 24-core / 32-thread desktop. Both genuinely compile from scratch: the C++ ran in a private Bazel output base with the disk cache disabled, the Rust in a fresh CARGO_TARGET_DIR. Neither timing includes downloading dependencies — external repositories and the crates.io registry were already present, because the interesting question is compile cost, not network weather.
Why the gap is this wide
It is tempting to say "Rust is faster to build than C++", which is not generally true and is not what happened here. Three specific things did.
The dependency tree shrank enormously. The C++ service pulls gRPC, protobuf, abseil, capstone, libunwindstack, and their transitive closure — 4,506 actions worth. The Rust service reaches the same capabilities through 116 small crates, and the biggest single win was earlier in the port: deleting six LLVM libraries in favour of object, gimli, pdb and msvc-demangler. That change alone took ObjectUtils's cold build from 158.7 s to 104.6 s, a third off one target, before any of the rest existed.
There is no header model to re-expand. C++ recompiles the same headers into every translation unit that includes them; the work is quadratic in a way that tooling can mitigate but not remove. Rust compiles each crate once and hands the next crate metadata. A 116-crate graph parallelises cleanly — the cold build ran at 1,052% CPU, so roughly ten cores stayed busy.
Nothing is generated. The pod wire format replaced protobuf on the capture path, so there is no schema compiler in the build at all: no protoc, no generated sources, no plugin. The format is a tag byte and fixed fields, and the thing that reads it is ordinary Rust.
What the number does not say
- These are not the same program. The C++ service carries gRPC transport, the symbol services, dynamic instrumentation and years of features the Rust one has not reached. Some of the gap is genuinely "less code doing less". The parts that are ported were verified against their C++ originals event for event and byte for byte, but a build-time comparison between a complete service and a growing one flatters the newcomer, and saying so is part of reporting it.
- Bazel is not cargo. Bazel buys hermeticity, remote caching and a shared graph across a large C++ tree; cargo buys none of that. In CI with a warm remote cache the C++ number would fall a lot. This measures the local from-scratch experience, which is the one that decides whether you try the second idea.
- The Rust service grew while this was being written. Adding the live-viewer UI server pulled in axum and tokio and took the static binary from 865 KB to about 12 MB. The build stayed near eleven seconds, but the trend is the honest thing to watch: this number is not a trophy, it is a reading that has to be retaken.
Why eleven seconds is a different activity
Two and a half minutes is long enough to switch context. You start the build, read something, come back, and reload what you were doing. Eleven seconds is not — you watch it finish. Five seconds, the incremental case, is inside the window where a build feels like part of the edit rather than an interruption.
That difference shows up in behaviour, not just in a table. Almost every measurement in this log — the differentials over millions of instructions, the sabotage checks that deliberately break the Rust to prove the harness bites — exists because rebuilding to test a hypothesis was cheap. The habit of checking rather than assuming is affordable at eleven seconds and expensive at two and a half minutes. That is the real return on "ease of build", and it is not visible in the number itself.