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.
The one rule
Section titled “The one rule” ┌─────────────────────────────────────────────────────────┐ │ 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.
What you’ll build (and break, and fix)
Section titled “What you’ll build (and break, and fix)”- A load test of
quillwithoha/wrkthat gives you a baseline: requests/sec and p50/p99 latency for the list, read, and draft paths. - A profiling toolkit:
criterionfor microbenchmarks,cargo-flamegraphfor CPU, andtokio-consoleto 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 win | How you claim it | How people lose it |
|---|---|---|
| No GC pauses | nothing to do — it’s free | blocking the async runtime instead |
| Zero-cost abstractions | iterators, async compile to tight code | boxing/dyn on the hot path unnecessarily |
| Stack + ownership | pass references, reuse buffers | cloning String/Vec in a loop |
| Real parallelism | tokio across cores | one undersized pool serializing everything |
The chapters
Section titled “The chapters”| Ch | Title | You add | The idea it teaches |
|---|---|---|---|
| 1 | Measure first | load test, baseline, criterion | benchmarking honestly, variance, the baseline number |
| 2 | Find the bottleneck | flamegraphs, tokio-console | reading a profile, the blocking-call trap |
| 3 | Fix and prove it | clones, pools, cache, serialization | one change at a time, before/after, when to stop |
The thread
Section titled “The thread”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.