Machines and programs
How code runs
From source file to running instructions. Covers the CPU's loop, compilers, interpreters and JITs, branch prediction and the system call boundary.
You write total += i in a text file. A few milliseconds later, a chip the size of a fingernail runs that addition a hundred million times. In between, a compiler or interpreter, a language runtime, the OS kernel and the CPU itself all change how your program runs.
Most of the time you can ignore all of that. You can't when a service runs 50× slower than it should, a serverless function has a 2-second cold start, or a p99 spike has no obvious cause. Those problems need a model of the whole stack.
Read the stack from the bottom up. The CPU runs one simple loop very fast. The language decides how much work each source line turns into. The kernel is the only door to the outside world.
Concepts in this section
Read them in order. Each one builds on the one before.
| Step | Concept | What it answers |
|---|---|---|
| 1 | The CPU loop | What does a core do billions of times a second? |
| 2 | Compiled, interpreted and JIT | Why is the same loop 57× slower in Python than in Go? |
| 3 | Branch prediction | Why does sorting an array make an unrelated loop faster? |
| 4 | System calls | What does a program need the kernel for, and what does it cost? |
Common mistakes
- Reasoning only from big-O. The same algorithm can run 50× apart depending on language and data layout.
- Benchmarking the first seconds of a JVM or Node process. JIT warm-up makes early numbers too slow.
- Assuming the compiler removed your work. Check with a tool such as Compiler Explorer before you trust it.
- Reading high CPU as "busy". Many services spend their time waiting on memory or the kernel.
Key takeaways
- A core runs fetch, decode and execute at 3–5 GHz. Modern cores overlap several instructions per cycle, but most server code is held back by waiting for data.
- Compiled, interpreted and JIT languages pay their costs at different times: build time, every operation, or during warm-up.
- Unpredictable branches in hot loops are slow. Compilers often remove them.
- A system call is the only way into the kernel. It costs roughly 100 ns to 1 µs, so batch small writes.
Further learning
Tom Scott's short explainer is the clearest 10-minute introduction to the fetch-execute cycle, if you have never seen it animated.
Computer Systems: A Programmer's Perspective covers the full stack from this page in depth.
Nand2Tetris builds a computer from logic gates up, if you want the bottom layer.
Related
The memory hierarchy
From registers to SSDs to the network, the latency numbers that dominate performance, and why the tier your data sits in matters more than the code you write.
Processes, threads and the kernel
What the OS gives every program, and how to see it on a live Linux box. Start here for the process model.
Performance and profiling
How to find where time goes before you optimize. Percentiles, two predictive laws, sampling profilers, off-CPU waiting and honest benchmarks, with a worked investigation of a slow endpoint. Start here for the performance toolkit.