This episode features Casey Muratori, a veteran game developer and performance advocate, discussing why most software runs 10–100× slower than hardware allows, how the industry lost its performance focus, and what engineers can do to reclaim it — covering optimization methodology, assembly literacy, architectural decisions, game industry history, AI’s impact on craft, and the value of reading research papers.
Casey Muratori’s background and path into games
Casey learned programming at age seven from his father, a programmer at Digital Equipment Corporation (DEC), giving him early access to computers in the early 1980s.
He interned at Microsoft in the early 1990s, arriving just as the “WinG” project (a skunkworks fast-blit library for Windows) blew up and his intended manager, Michael Edwards, stormed out.
Through Chris Hecker (WinG’s creator), Casey met game developers like Ron Gilbert and entered the game industry.
He worked at Gas Powered Games (Dungeon Siege), then Rad Game Tools (building the Granny 3D animation system, still used today), then went independent under Molly Rocket.
He contributed to The Witness (movement system) and now runs Computer Enhance, a Substack teaching performance engineering, while working on an unannounced game project.
Why performance matters and why it’s widely ignored
Enterprise software: The buyer (e.g., HR director) evaluates cost, compliance, legal liability — not the 30-second pause when opening a record. Users suffer but can’t switch.
Monopoly/network effects: Social networks (X, Facebook, TikTok) own their spaces; performance alone can’t displace them without a distribution strategy.
Tide is turning: Over the past decade, advocacy (including Casey’s) has shifted mindsets. New products like File Pilot, Blink editor, Bun (vs. npm), and Linear (vs. Jira) win with performance-based pitches.
Napkin math / back-of-the-envelope: Most engineers don’t know hardware’s theoretical limits. Simon Eskildsen (TurboPuffer) found Shopify teams benchmarking wrong — e.g., 10s for an operation that should take 100ms — because they lacked baseline intuition.
How optimization is actually done (vs. the common misconception)
Misconception: Profile → find hotspots → tweak → measure statistics → repeat. This only finds local minima.
Correct approach:
Identify the operations the system must perform.
Determine the hardware’s theoretical peak for those operations.
Measure the delta between actual and theoretical.
Shrink the gap by explaining why you’re not at peak (e.g., memory bandwidth, dependency chains, instruction throughput).
Why it matters: Without a theoretical ceiling, you can’t spot anomalies (e.g., unknown CPU behaviors like new register-renaming features) or learn new hardware capabilities.
Result: This method is how every great optimizer Casey has worked with operates.
Why you should learn to read assembly
Assembly is the CPU’s actual input: High-level code (C, Rust, Python, JS) is compiler input; only assembly shows what the CPU is asked to do.
Reading ≠ writing: You rarely write assembly, but reading it is essential for optimization — you verify the compiler didn’t emit nonsense.
It’s simpler than you think: Only ~20–30 common instructions appear in 90% of compiler output (x86-64). If you can vertically center a div in CSS, you can learn assembly.
Unlocks hardware knowledge: CPU block diagrams (e.g., Zen 5, Apple M-series) become readable — you see throughput for multiplies, loads, branch prediction, cache hierarchy.
Python example: A + B in Python compiles to ~100× more instructions than in C. Understanding this explains why you must use C libraries (NumPy, etc.) for heavy lifting in Python.
Designing for optimization: architecture over hotspots
“Premature optimization is the root of all evil”: Often used to avoid thinking about performance. Casey has a 2-hour lecture on this phrase (linked in show notes).
When deferring works: Isolated, optimizable hotspots (e.g., a slow hash map) where architecture won’t change.
When it fails: Architectural decisions that create serial dependency chains — e.g., await server → compute → await server → compute — that no hotspot fix can resolve without a rewrite.
Key insight: You must engineer for a hotspot-friendly architecture upfront. Every architect must know performance to avoid foreclosing optimization paths.
Real-world proof: Facebook, Uber, OpenAI, Anthropic all rewrote entire stacks (Python/Node → Rust/Go/Java) because early architectural choices (single-threaded, synchronous) couldn’t scale — not because of hotspots.
How to get better at writing performant software
Good news: You don’t need to be a hyper-optimizer. Modern CPUs and libraries handle micro-optimizations. Target: within 2× of theoretical (vs. 100× typical).
Learning path (1–2 months of nights):
Learn to read assembly (x86-64 or ARM64).
Study CPU basics: cache hierarchy (L1/L2/L3), load/store units, branch prediction, instruction throughput, µop scheduling.
Do timing experiments: measure latency/throughput of real operations.
Internalize orders of magnitude: e.g., Python + vs. C add, network RTT vs. local compute.
Payoff: You make better architectural choices in any language — e.g., batch server calls, use SIMD-friendly layouts, pick the right library — without becoming a low-level specialist.
Understanding how the CPU works (why it matters for non-game devs)
Three mental models:
Data movement: Cache lines, L1/L2/L3, granularity, policies — determines whether your access pattern streams or stalls.
Instruction flow: Branch prediction, I-cache misses, dependency chains — determines whether the front-end feeds the back-end.
Black-box approach: You don’t need transistor-level docs. CPU vendor diagrams (e.g., “Zen 5 microarchitecture”) become readable once you know assembly.
Craftsmanship & satisfaction: Engineers who understand the machine feel more fulfilled — they know why code behaves as it does.
Leverage: If library authors internalize this, all downstream code gets faster. Performance knowledge compounds.
Building games then vs. now
Pre-engine era (1990s–early 2000s): Every studio built its own renderer, tools, physics. Engine was the studio’s moat (e.g., id Tech, Bullfrog’s pseudo-3D). Two huge risks: engine risk (can we build it fast enough?) and gameplay risk (is it fun?).
Mitigation: Grit for engine risk; vertical-slice prototyping (build one playable level hackily, prove fun, then scale) for gameplay risk.
Engine licensing (Unreal, Unity, Godot): Eliminated engine risk, democratized creation → massive release volume (tens of thousands/year on Steam).
Consequence: Organic discovery died. Marketing/distribution strategy is now mandatory. Great game = table stakes, not differentiator.
Old games compete with new: Audiovisual fidelity plateaued (2017 games still look fine). Live services (Fortnite, Minecraft, League) consume entertainment hours zero-sum.
GTA 6: why 10+ years?
Not a sequel — a replacement: GTA 5 Online generates billions/year. GTA 6 must replace the most profitable entertainment product ever without cannibalizing it.
Business risk: Ship too early → worse live ops → less revenue. Ship too late → opportunity cost. Rockstar/Take-Two are optimizing for live-service transition success, not just single-player launch.
Red Dead Online didn’t hit GTA 5 heights; GTA 6 is their first “true update” to a known blockbuster — equivalent to relaunching Google Search.
Casey’s critique of “Clean Code” (Uncle Bob Martin)
Video: “Clean Code, Horrible Performance” — shows polymorphism-heavy refactoring runs 1.5–15× slower than a switch/table-driven approach.
Core issue: Rules like “prefer polymorphism,” “tiny functions,” “no runtime type knowledge” block compiler optimizations (inlining, vectorization, dead-code elimination).
Virtual calls aren’t the cost — it’s the opacity they create. Compiler can’t see through virtual to optimize.
Small static functions are fine — compiler inlines and widens them. The dogma becomes harmful when applied blindly.
Response: Surprisingly positive. Many engineers recognized the disconnect between “clean” dogma and measurable performance.
TDD: pragmatic, not dogmatic
Test if it saves total time: Writing/maintaining tests must cost less than the bugs they catch in production.
Used regression testing at Rad for core libraries — valuable because customers depended on correctness.
Anti-pattern: “Test-driven” as a default. Development should be engineering-driven; tests are a tool you evaluate per project.
Hidden costs: Tests ossify code (harder to refactor), consume maintenance time. Include these in the calculus.
What is good code?
Straightforward mapping from problem to machine operations.
Decomposed into named, digestible pieces (e.g., euclidean_distance() not scattered math).
Compiler-friendly: Structured so the optimizer can inline, vectorize, eliminate redundancy.
Nexus: Readable, maintainable, fast enough (within 2× of peak), and leaves the door open for future optimization.
Only at the extreme tail (last 1–2% of theoretical) does readability trade off against speed — and that’s rare.
What makes a great software engineer?
No single archetype — like baseball: pitchers, hitters, fielders all great in different ways.
Types Casey has seen:
Utility infielder: Drops into any messy codebase, quickly understands, patches effectively.
Deep diver: Spends 8 months on one problem, invents new algorithms, pushes boundaries.
Non-negotiables (common traits):
Curiosity about the machine: Almost every great engineer Casey knows can read assembly / understands CPU basics — even if they don’t use it daily, it prevents architectural blunders.
Skepticism of received wisdom: “Always use memset,” “never use if,” “prefer polymorphism” — most are untested nonsense. Great engineers measure and experiment before adopting.
Focus on what works in practice: Demonstrable, repeatable results > conference talks or blog posts.
Why Casey doesn’t code with AI
Philosophical, not productivity: He programs because he wants to program. If he wanted AI to do it, he’d use Unreal Engine.
Craft preservation: Like hand-knitting vs. factory hats, or artisanal furniture vs. IKEA — humans keep doing things by hand because making is the point.
Not anti-AI: Acknowledges it may become a “traditional craft” niche. He wants to be part of keeping that craft alive.
AI’s impact on the game industry (and beyond)
Parallel to engine democratization: Engines lowered barrier → flood of games → marketing became mandatory. AI may do the same for code.
Too early to assess: Serious adoption only ~6 months old. Workflows still shaking out. No visible 10× output jump (e.g., Fortnite still ships weekly with large teams).
Possible outcomes:
Small uplift (10%) — hard to observe externally.
Workflow revolution — needs better tools + human adaptation.
“AI using you” — some big-tech mandates feel like training-data generation for replacement.
Burnout/fatigue: Engineers with low autonomy (ticket-takers) feel threatened; high-autonomy engineers use AI for drudgery and enjoy it. Autonomy predicts AI experience quality.
Why you should read papers (not just books)
Hot take: Don’t ask Casey for book recommendations. Read research papers.
Method: Pick your domain → Google Scholar → read a survey → crawl references → read those.
Payoff: Discovers techniques no blog covers, builds historical context, compounds knowledge. AI can likely help find relevant papers too.
Habit: Casey does this for every new domain he enters — it’s how he stays current without memorizing everything.