Reading Assembly

Part 6 · Speaking performance

Explaining performance to your team

The last lesson. Six conversations a tech lead actually has — including the one where knowing assembly means telling someone not to use it.

40 minauthentic taskarticulation
What this lesson is trying to break (2)
  • Knowing assembly means you should hand-optimise.
  • A lead who understands performance should push for it.

You now know enough to be dangerous. This lesson is mostly about not being.

1. “I rewrote it in assembly and it’s faster”

The tempting response is enthusiasm. The useful one starts with a question.

“Nice — what did you measure, and what fraction of total runtime was it before? If it was 2% of runtime, a 3× win on it is a 1.3% win overall, and we’ve traded that for code only you can maintain and that breaks on ARM.”

Then the substance:

“Before we keep it — did you try giving the compiler better information instead? restrict on those pointers, or a known trip count? Those usually get most of the win and cost nothing in maintainability.”

When hand-written assembly is genuinely right: a specific instruction with no intrinsic (some crypto, some bit manipulation); constant-time guarantees where you need to control the exact sequence for security; a measured hot loop where you have exhausted the free options. That is a short list, and none of the entries is “ordinary application code”.

2. “Should we micro-optimise this?”

The frame that keeps this short:

“Three questions. Is it hot — what fraction of runtime? Is it compute-bound or memory-bound? And have we tried the free options? If we can’t answer the first two, we’re guessing.”

The IPC number from 6.2 settles the second in one measurement, and it very often redirects the work entirely: most code that looks like it needs faster arithmetic actually needs better data layout.

3. “Why is this slow? The algorithm is O(n)”

“Complexity ignores constants, and cache behaviour is a constant of about 50. A linked list and an array are both O(n) to traverse, and the array can be ten times faster — same complexity, completely different locality.”

This is worth having ready because it is a genuinely common blind spot in strong engineers. Algorithmic thinking is necessary and not sufficient, and the gap is exactly 4.4.

4. “Which is faster, x86 or ARM?”

“Not a well-formed question any more. The high-end cores are more alike than different — both wide, out-of-order, speculative, similar caches. The real differences are decode cost, the memory model, which matters for lock-free code, and vector width. Instruction counts across ISAs are not comparable, because x86 folds loads into arithmetic and ARM64 doesn’t.”

If pressed on what actually decides it: the memory subsystem and the specific implementation, not the ISA. And for most services, neither — you are I/O bound.

5. “Can you review this performance PR?”

You can do this usefully without being the fastest programmer in the room. The checklist:

Varies: what you can check without deep expertise

Look forAskWhy
A measurement in the descriptionHardware, data size, variance, and share of total runtime?Without it the change is speculative
Instruction-count reasoning“Did IPC change, or just the count?”Fewer instructions on a stalling core changes nothing
Hand-unrolled loops“Did you check for spills?”Over-unrolling causes spilling and can be slower
-ffast-math added“Which results change, and does anything check for NaN?”It permits far more than reassociation
New unsafe or intrinsics“What breaks on the other architecture?”Portability and safety cost, often unnoticed
A data-structure change“What happened to cache behaviour?”Usually the largest real effect, often unmentioned

Every row is answerable without reading the assembly. The point is to make the reasoning explicit, not to out-optimise the author.

6. “Should we care about any of this?”

The honest answer, and the one that makes the rest credible:

“Usually not. Most of our code is I/O-bound and most of the rest is not hot. This matters in three places: a measured hot loop, anything where latency is a product requirement, and choosing data structures — where the cache effects are big enough to matter even in code that isn’t hot.”

“What it’s mostly for is not being fooled. Being able to say ‘that benchmark measured nothing because the result was unused’, or ‘that’s memory-bound so this won’t help’, saves more time than any optimisation I’ve ever written.”

That is the real value proposition of this course, and it is worth being explicit about it: the return on reading assembly is mostly in rejected work.

The exit test

You are done when you can do these out loud, without notes:

  1. Explain why lea rax, [rdi+rdi*2] touches no memory.
  2. Explain what xor eax, eax does that mov eax, 0 does not.
  3. Explain why the first argument is in rdi and what would break that.
  4. Read a multiply-by-a-strange-constant and say what was in the source.
  5. Explain why fewer instructions can be slower, in two sentences.
  6. Explain why sorting an array can speed up a loop over it.
  7. Say what the CPU actually executes, and why the distinction matters.
  8. Look at an IPC number and say what to do next.
  9. Tell a colleague not to hand-optimise something, with a reason they accept.

Number 9 is the hardest and the most valuable.

The last onewrite it — thinking it does not count

Pick the conversation above you are most likely to have in the next three months. Write the actual words you would say — not notes.

Then find a colleague and have it. That is the articulation step, and it is the one part of this course the site cannot do for you.

Where to go now

  • Keep the Review queue running. Fifteen minutes a week holds this; without retrieval most of it decays.
  • Read one listing a month. Take a function you wrote, compile it, and explain the output to yourself. Reading is the skill, and it decays fastest.
  • Profile something real. Preferably something you believed was fast.
  • Check Calibration against your Part 0 baseline. If the gap between confidence and accuracy has narrowed, that is the actual result of this course — not the facts, but knowing how far to trust yourself when you are about to say something in a design review.

And if you came from Reading Rust: the two courses now meet. You know what ownership costs, what &mut buys the optimiser, why dyn is not free, and how to check any of it rather than repeat it.

In the wildgo read the real thing now, while it is fresh
Scheduled for recall3 items added to your review queue

These are not shown to you now on purpose. They will surface in Review tomorrow, mixed in among items from other parts of the course — not grouped by topic. Sorting out which idea applies is the part that transfers.