Guide

A modern core can add two numbers in about a third of a nanosecond. Fetching those numbers from main memory takes about 100 ns, roughly 300 to 400 times longer. An SSD is about 1,000 times slower again, and a server on another continent is slower still. Most performance problems come down to which tier your data was sitting in.

Computers handle this with a hierarchy: small, fast, expensive storage close to the core, and large, slow, cheap storage further away. Each level caches the one below it. The numbers below are the ones to remember, and they change little from one hardware generation to the next.

OperationTypical latencyIn CPU cycles at ~4 GHzIf 1 ns were 1 second
Register access, simple ALU op~0.3 ns10.3 s
L1 cache hit~1 ns~41 s
Branch mispredict~5 ns~15–205 s
L2 cache hit~4 ns~12–154 s
L3 cache hit~10–40 ns~40–15010–40 s
Main memory (DRAM)~100 ns~4001.5 minutes
Mutex lock/unlock (uncontended)~20 ns~8020 s
Compress 1 KB with a fast codec~1–3 µsthousands~1 hour
NVMe SSD random 4 KB read~20–100 µs~100,000~1 day
Round trip within a datacenter~100–500 µs~1 million~2–6 days
Read 1 MB sequentially from NVMe~200–500 µs~1 million~2–6 days
HDD seek~5–10 ms~30 million2–4 months
Round trip, US East to US West~60–70 ms~250 million~2 years
Round trip, cross-continent (US to Europe or Asia)~70–150 ms~500 million2–5 years

The right-hand column gives intuition. If an L1 hit took one second, a DRAM access would be a coffee break, an SSD read would cost a day, and a request to Europe would take years.

Why it matters

Most code is written as if every variable access were equally cheap. It isn't. A hash map with 50 million entries and a hash map with 50,000 entries can run the same code 10 to 20 times apart, because only the small one fits in cache. The same logic applies to a loop that calls another service once per item instead of once per page.

Concepts in this section

Read them in order. Each builds on the one before.

StepConceptWhat it answers
1Reasoning with latency and bandwidthHow do you turn the table into a cost estimate?
2Cache lines and localityWhy does walking an array beat following pointers?
3Array of structs vs struct of arraysHow should you lay out records in memory?
4False sharing and NUMAWhy can adding threads make code slower?

Common mistakes

  • Reasoning only in big-O. A search over a pointer-based tree with 30 cache misses can lose to a scan over a small, contiguous array.
  • Benchmarking with hot caches. A 10 KB input in a loop measures L1, not production behavior.
  • Ignoring the network tier. A synchronous cross-region call costs more than a million L1 hits.
  • Adding threads to a memory-bound job. If one thread already saturates memory bandwidth, more threads just compete for it.

Key takeaways

  • Memorize the orders of magnitude: L1 about 1 ns, DRAM about 100 ns, NVMe 20 to 100 µs, datacenter round trip 0.1 to 0.5 ms, cross-continent 70 to 150 ms. Each step is roughly 100 to 1,000 times slower than the one before.
  • Caches move whole lines of 64 bytes (128 on Apple Silicon). Access that is sequential and contiguous is fast. Pointer chasing pays full latency at every hop.
  • Layout and traversal order can change speed several times over with identical arithmetic.
  • Throughput depends on concurrency and latency together. Multi-socket and multi-core machines add their own traps.

Further learning

Scott Meyers' talk is the classic introduction to why CPU caches matter for ordinary code, with benchmarks of traversal order, false sharing and data layout.

code::dive conference 2014 - Scott Meyers: Cpu Caches and Why You CareNOKIA Technology Center Wrocław

Latency numbers every programmer should know is a short reference for the table above.

Gallery of Processor Cache Effects shows each effect with a small benchmark.