Performance and tradeoffs
When to care about speed, how to find the real bottleneck, and what you trade for it.
- Decide when performance work is worth doing
- Find the real bottleneck by measuring, not guessing
- Reason about the trade-offs every optimisation makes
Performance work is seductive — it feels productive and clever. But most of it is wasted, aimed at code that was never slow, while the real bottleneck goes untouched. This closing lesson is about doing it deliberately: knowing when speed matters, finding what's actually slow, and understanding what every optimisation costs.
Make it work, make it right, make it fast — in that order
The classic sequence is a priority list. First make it work (correct output). Then make it right (clean, clear, well-structured). Only then, if needed, make it fast. Optimising code that's still wrong or unclear is effort spent on the wrong layer — and clear code is far easier to speed up later.
Measure, don't guess
Human intuition about performance is famously bad. The slow part is rarely where you think. So before changing anything:
- Profile — use a tool that measures where time (or memory) actually goes.
- Find the bottleneck — usually a small fraction of the code accounts for most of the cost. Optimising anywhere else is invisible to the user.
- Optimise that, then measure again — confirm you actually helped, and that the bottleneck didn't just move.
This connects directly to complexity: the biggest wins are almost always algorithmic — an O(n²) loop becoming O(n) — not micro-tweaks to fast code.
Everything is a trade-off
Optimisation is rarely free; you're usually trading one resource for another:
- Caching trades memory (and the risk of stale data) for speed. "There are only two hard problems: cache invalidation and naming things" is a joke about a very real cost.
- Precomputing trades upfront work and storage for faster reads later.
- Cleverer algorithms often trade readability for speed — a real cost, since code is read far more than it's run.
Name the trade before you make it. A 5% speedup that doubles the complexity of a non-critical path is a bad deal.
Premature optimisation wastes effort and adds complexity that breeds bugs. But ignoring a genuine O(n²) on a path that will see large input is the opposite sin. The whole skill is telling the two apart — which is why complexity came first.
You've finished the track
That completes Systems & Structure. You can now reason about whole systems — their flows, boundaries, costs, correctness, and trade-offs — and direct AI agents with the judgement that makes them genuinely useful. Put it into practice in the Python and JavaScript/TS tracks, and revisit any lesson from the Curriculum page to track your progress.