Skip to content

Part 6 · Make It Fast — Optimization

People choose Rust “because it’s fast,” then write Rust that isn’t — needless clones, a blocking call on the async runtime, a connection pool of one, JSON serialized twice. Speed isn’t a property of the language; it’s a property of code you measured and fixed. Part 6 is the discipline that separates “I use Rust” from “I made this fast”: profile the real quill under real load, find the actual bottleneck, fix it, and prove the fix with numbers.

┌─────────────────────────────────────────────────────────┐
│ MEASURE ─► find the real bottleneck ─► fix THAT │
│ ▲ │ │
│ └─────────── measure again ◄─────────────┘ │
└─────────────────────────────────────────────────────────┘
Never optimize what you haven't measured. Ever.

Every instinct about “what’s slow” is wrong often enough that guessing is a bug. The whole part is built around a loop: establish a baseline, profile to find the hottest thing, change exactly one thing, re-measure, keep or revert.

  • A load test of quill with oha/wrk that gives you a baseline: requests/sec and p50/p99 latency for the list, read, and draft paths.
  • A profiling toolkit: criterion for microbenchmarks, cargo-flamegraph for CPU, and tokio-console to catch tasks that block the async runtime.
  • A sequence of real fixes on quill, each with a before/after: kill an accidental .clone() in a hot handler, move a blocking call off the runtime, right-size the connection pool, add the Part 4 cache to the hottest read, and serialize once instead of twice.

Where Rust’s speed comes from — and how to lose it

Section titled “Where Rust’s speed comes from — and how to lose it”
The winHow you claim itHow people lose it
No GC pausesnothing to do — it’s freeblocking the async runtime instead
Zero-cost abstractionsiterators, async compile to tight codeboxing/dyn on the hot path unnecessarily
Stack + ownershippass references, reuse bufferscloning String/Vec in a loop
Real parallelismtokio across coresone undersized pool serializing everything
ChTitleYou addThe idea it teaches
1Measure firstload test, baseline, criterionbenchmarking honestly, variance, the baseline number
2Find the bottleneckflamegraphs, tokio-consolereading a profile, the blocking-call trap
3Fix and prove itclones, pools, cache, serializationone change at a time, before/after, when to stop

Once it compiles, what does it take to run for real users? Part 6’s answer: performance is evidence, not vibes. You don’t get to say your Rust service is fast; you get to show a flamegraph, a before/after p99, and a load-test graph. That habit — measure, change one thing, measure again — is the most transferable skill in this entire book.

Next: Part 7 · Ship It & What’s Next →