· 4 min read

Two kinds of control

One reproducible Rust–Odin run retires a compile-speed slogan and a runtime slogan, then traces what remains to where each language places control.

A long historic machine shop filled with rows of lathes, mills, belts, benches, and hand controls.
Historic American Engineering Record, Public domain

Rust out-compiled Odin in every fixture of this recorded run, and the matched runtime programs finished within three percent of each other. If both results feel backwards, that is the slogans talking — “the simple language builds faster” and “the borrow checker buys faster code” each walked into this benchmark, and neither walked out.

A language benchmark measures a toolchain distribution, a build strategy, generated code, and two standard libraries all at once, which is how it can embarrass both camps in one table. So the useful version of the exercise is narrow: reproduce the artifacts, disclose the confounders, and connect the numbers to where each language actually places control.

Recorded conditions#

The run used a GitHub Actions ubuntu-latest machine exposing two logical CPUs from an AMD EPYC 9V74 host, with Rust 1.97.0 on LLVM 22.1.6 against Odin dev-2026-07-nightly:819fdc7. The benchmark record keeps everything needed to argue with it: the workflow, generated fixtures, raw Hyperfine JSON, checksums, resident-memory readings, binary sizes, and toolchain output.

The compile fixture generated 256 dependency-free files per language, timed clean development and optimized builds over five measured runs after a warm-up, and let Cargo keep incremental state for the one-leaf edit. Optimized Rust meant one codegen unit, ThinLTO, and aborting panics; Odin got -o:speed.

BuildRust medianOdin medianOdin / Rust
One file, default62.7 ms720.3 ms11.5×
256 files, clean development245.3 ms926.9 ms3.8×
One leaf edited, warm state214.9 ms943.0 ms4.4×
256 files, clean optimized3.195 s3.511 s1.10×
Complete installed toolchains were timed, with lower results better.

Resist the headline row. The 11.5× on one tiny file mostly measures startup and distribution choices — Rust ships a prebuilt standard library — and the gap narrows to ten percent on the optimized build, where both pipelines spend their time marinating in LLVM. A different crate graph, procedural macros, or another Odin configuration could reorder the whole table.

Matched runtime work#

Three optimized native pairs printed identical checksums before any timing started. The scan made twelve branchy passes over eight million integers, the tree fixture walked a flat complete binary tree ten times, and the map fixture inserted 1.5 million mixed integer keys before five lookup passes — ten Hyperfine runs after three warm-ups, with peak resident memory from a separate single run.

WorkloadRust medianOdin medianLeadPeak RSS Rust / Odin
Integer scan572.7 ms587.6 msRust 2.6%62.97 / 62.74 MiB
Flat tree traversal97.8 ms95.8 msOdin 2.1%65.94 / 65.73 MiB
Default hash map581.9 ms759.4 msRust 30.5%35.93 / 49.77 MiB
Matched checksums precede every timing. RSS should be read more coarsely than the medians.

The scan and tree rows are a tie for any practical purpose; two and three percent on one shared runner supports no broad conclusion. The interesting row is the map, and it is a library comparison wearing a language costume — each side's default container and hashing policy owns that 30.5 percent as much as either compiler does. Swap containers and you have started a different experiment.

Binary size draws one more boundary worth keeping visible: 430,848 unstripped bytes for the Rust scan against 222,000 for Odin. Startup objects, panic policy, and standard-library linkage all live inside those artifacts, so the record refuses to call the difference pure code generation.

Two placements of control#

What the table cannot show is what each language spends its budget on. Rust's ownership model lets a library encode exclusive mutation and destruction rules for callers it has never met — reusable proofs, paid for in design effort and compile time. Odin's allocator model routes policy through an implicit context and leaves cleanup at the call site with defer, keeping the executable's memory plan next to the code that owns it.

No benchmark selects between those boundaries; this one only retires two slogans on its own fixtures. The raw files hold the evidence in both directions — runtime-tree.json still gives Odin a 1.98-millisecond lead, compile-tiny.json gives Rust more than 650 milliseconds — and an honest report prints both rows.