YouTube Summaries

← All summaries

Optimization is architecture, not hotspots

2026-08-26 Wed ⏱ 1 hr 53 min pragmaticengineer

Casey Muratori (Molly Rocket, Handmade Hero, Computer, Enhance) argues most software runs 10-100x slower than it should, and that the usual profile-and-patch-the-hotspot ritual is not how real optimization works. The real lever is architectural: know the hardware's theoretical maximum, measure your delta from it, and avoid design decisions that foreclose optimization later. Also covers reading assembly as a practical skill, his critique of "clean code" and TDD, how game development changed after licensable engines, and why he writes all his code by hand.

Why the industry ignores performance

Three reasons the zeitgeist doesn't care. First, for much enterprise software the user is not the purchaser - the buying decision is made on cost, compliance and legal liability, never on whether a record lookup takes 30 seconds. Second, monopoly effects: performance alone can't dislodge an incumbent network, so being faster is a nice plus rather than a wedge. Third - and Casey thinks this is genuinely improving - a decade of people arguing for performance has moved the needle. Products like Bun, Linear, File Pilot and the Blick video editor are attacking incumbents with performance-based pitches and getting traction.

Orosz notes Linear's pitch is a 300ms budget for any action. Casey's reaction: 300ms is an eternity in computing, and the fact that it reads as impressive shows how far the bar has fallen. Packets cross physical continents in under 10ms while apps fail simple operations in seconds.

The wrong and right models of optimization

The received model - run a profiler, find the big bars, change things, check whether statistics improved - is not how good optimizers work. All that finds is a local minimum. That's improvement, not optimization.

The correct method: enumerate the operations the system must perform, work out what the hardware could theoretically do at peak, measure the delta, then shrink the gap to something you can plausibly explain. You usually can't hit theoretical - that's why it's called theoretical - but the delta is the thing you manage.

The theoretical number also serves as a learning instrument. Without it you can't tell when something anomalous is happening. Casey has found undocumented CPU behaviours (a register-renaming table on recent Intel chips) precisely because the measured number didn't match the model. This is the same discipline as Simon Eskildsen's "napkin math"; Orosz recounts Shopify teams picking database vendors from homegrown benchmarks that were an order of magnitude off theoretical limits - the benchmarks were simply wrong, and nobody noticed because nobody knew the ceiling.

Premature optimization, correctly scoped

Casey doesn't dismiss "premature optimization is the root of all evil" outright. Deferring optimization is fine when you know the slow thing is a localized hotspot: a naive sort or hash table you can swap later without touching the architecture around it. That's real engineering judgment.

The failure case is when you don't know whether your choice produces an optimizable hotspot. His example: a codebase where every operation is written as "ask the server, compute, ask the server, compute." That creates a serial dependency chain, and performance is governed by the longest serial dependency chain, which cannot be parallelized, amortized or multithreaded. Call in performance experts at the end and the answer is "there's nothing we can do" - you have to rewrite. Had the paradigm instead been "at the top of every operation, batch every request you might need," the problem never arises.

The takeaway: a codebase does not become hotspot-shaped by accident. You have to engineer upfront for a hotspot codebase that someone can later optimize. Anyone making architectural decisions must understand performance, or they're rolling dice. The industry's steady stream of "we rewrote the whole thing for performance" blog posts (Uber's Python/Node to Go/Java, OpenAI and Anthropic now moving Python services to Rust) is the evidence: if performance problems were really always hotspots, whole-system rewrites would never be necessary.

Learning to read assembly

Reading assembly matters because every other language is input to a compiler - it tells you nothing about what the CPU is actually asked to do. The assembly output tells you exactly.

Writing assembly is almost never needed. Reading it is essential, and it is not hard: perhaps 20-30 instructions cover 90% of what compilers emit, against the vastly larger surface of JavaScript, the DOM, CSS and React that web developers already carry. "If you can vertically center a div in HTML, you can probably learn assembly language." It also unlocks the CPU architecture diagrams vendors publish with each new core - those charts are readable only if you know the instruction set.

Understanding the CPU

Assembly is the means; the CPU is the point. Three things worth modelling as a black box:

  • Data movement - load/store units, L1/L2/L3 (sometimes L0) cache levels, granularity and policy. How you lay out data and what your access pattern is can dominate, and these are architectural decisions that are hard to change later.
  • Instruction flow - branch misprediction, instruction-cache misses. Predictors get more complex, but the behaviour categories are simple to conceptualize.
  • Execution unit scheduling - raw throughput for float multiply, integer add, divide, and how instructions decompose into micro-operations.

You don't need to be a hyper-optimizer. Knowing the orders of magnitude is enough to make good decisions in any language. Casey's canonical demo: a + b in Python takes roughly a hundred times more CPU instructions than the same expression in C, which is one instruction. Internalizing that explains why Python work must be pushed into C libraries or Cython, and lets you decide upfront which parts of your program can afford a 100x penalty.

Two secondary arguments: craftsmanship - people report being far more satisfied once they understand what's happening underneath, even without changing what level they program at - and a percentages game, since convincing library maintainers to care makes everyone downstream faster. "The more people are doing performance, the less people need to do performance."

How games got built, and the engine transition

Before licensable engines, every studio built its own renderer, tools and pipeline, and that codebase was a large part of the studio's value. Two risks dominated: engine risk (can we build tech that does what this game needs, in time?) with essentially no mitigation available, and design risk (is the game any good?), which was brutal because you couldn't play the game until the engine and level tools existed. Thief: The Dark Project is the cautionary tale - the core gameplay reportedly only came together at the very end. The industry's answer was vertical-slice prototyping: throw the whole studio at one hacky playable slice, prove it's fun, then schedule everything else around it.

Casey's provocative framing: the arrival of Unity, Unreal and Godot was the game industry's AI transition, and the news is not entirely good. The early effect was positive - people who could never have marshalled the engineering talent got to make games. Then the market flooded. Steam now sees tens of thousands of releases a year, and organic discovery is essentially dead. A good game is table stakes; a real marketing and distribution strategy is mandatory. This is pre-AI, purely from the barrier to entry collapsing.

New games also increasingly compete with old ones. Technological advances no longer visibly date a game the way they did in 1995, so a 2017 title still looks fine, and live-service incumbents (Fortnite, Minecraft, League) consume entertainment hours in a zero-sum way.

On GTA 6 taking a decade: it isn't a game being sold to players, it's a replacement for GTA 5, which was among the most revenue-generating entertainment products ever built and is still printing money. Shipping a successor that cannibalizes it and earns less is the nightmare scenario. Casey likens it to relaunching Google Search.

Clean code, TDD, and what good code is

The "Clean Code, Horrible Performance" argument isn't about virtual calls being expensive per se. The cost is that the compiler can no longer see what's happening - it must leave open the possibility that a different class was substituted, so it can't inline, can't collapse redundant code, can't widen paths to vectorize. Lots of tiny functions are fine if they're statically resolvable within the translation unit; optimizing compilers are heroic. The specific rules - prefer polymorphism always, never know the type at runtime, cap function length - block that. You can write maintainable, readable code that doesn't follow them.

On TDD, Casey's objection is to the "driven" part. Tests are an engineering decision like any other: weigh the cost of writing and maintaining them, and the cost of a codebase that becomes harder to change because tests must be rewritten, against the bugs they'd catch. Sometimes the right answer is a lot of tests; sometimes very few. Development should not be driven by tests by default.

Good code, to him, is code that maps as directly as possible onto what the machine actually needs to do, broken into well-named digestible pieces, with no duplicated formulas scattered around. He rejects the premise that well-architected code and fast code are in tension - normally the simple readable version is the fast one. The divergence only appears far out on the curve, when you deliberately over-specialize for particular hardware. Good code sits at the nexus: runs well, reads well, isn't at theoretical maximum but hasn't foreclosed the path there.

What makes a good software engineer

There's no single archetype - it's a baseball team, not one position. He's seen excellent utility infielders who parachute into an ugly codebase, get the lay of the land fast and patch what needs patching, and excellent specialists who spend eight months grinding out one problem and emerge with a new algorithm. When staffing, think "great at this role," not "great engineer."

Two near-universal traits, though. Almost every great engineer he's known has some sense of what's actually going on down the stack, even if they rarely operate there - it's what stops them making architectural decisions that bite later. And, more importantly, not being dogmatic about things they haven't proved out themselves. Much received programming wisdom has never been tested; to qualify as wisdom it should at minimum demonstrate concrete upsides, and often it can't. Skepticism plus a bias toward what's demonstrable and measurable.

Why he doesn't use AI

Molly Rocket uses no AI tools at all. The reason is philosophical, not a productivity evaluation: he programs game systems because he wants to program them. "If I just wanted an AI to program them, I'd just go get the Unreal Engine." He expects a handcrafting tradition to persist the way it does after any automation wave - IKEA exists and so does the person welding strange iron-and-wood tables in the industrial district. Asked which he'd be, the answer is always the organic farming guy.

On AI's industry impact he thinks it's far too early to assess. The people whose judgment he trusts only found the tools usable recently; workflows haven't shaken out. Nothing obvious has happened - "Fortnite doesn't ship once a week now and bug-free." And a real 10% across-the-board uplift would be both impressive and externally invisible.

AI, autonomy and burnout

Orosz reports growing AI fatigue: engineers who were good at coding, now mostly prompting, losing their drive under pressure to be more productive with tools they didn't choose. Casey's read, echoing Armin Ronacher: it tracks autonomy. If you control your work, you reach for AI on exactly the tasks you didn't want to do, so the worst case is mild disappointment and the normal case is a win. If you're handed a ticket, told you must use the AI, and there were layoffs last quarter, the psychology inverts entirely. Casey's phrasing: "are you using an AI to do your job, or is an AI using you to do your job?" The practical implication is to weigh autonomy when evaluating your current or next position.

Closing recommendation: read papers

Instead of a book, Casey recommends reading papers - pick your domain, search Google Scholar, follow and crawl the references. He does this constantly before programming in an unfamiliar area and finds most programmers simply don't. Even when it only yields historical context it's worth it; often it surfaces entire techniques you didn't know existed.