Every Byte Matters
A clear reminder that big-O hides cache and working-set effects. Object size, field layout, and random access patterns can dominate performance before the algorithm changes at all.
Links: Original source
Logged at IST: 2026-08-05 08:44 IST
What it is: Farid Zakaria's post on how struct size, cache lines, and working-set size affect performance.
Gist: The post starts from a common blind spot: in large Java-style classes, adding another field rarely feels like a performance decision. Zakaria shows why it is one. A CPU cache line is 64 bytes on his machine, so reading one byte from memory often pulls the surrounding 64 bytes into cache. If your hot loop only needs a boolean like is_alive, an array-of-structs layout may still fetch a full object per element.
His Monster example makes the tradeoff concrete. With a 64-byte struct, scanning is_alive in an array of monsters gets one useful byte per cache line. In a struct-of-arrays layout, the is_alive bytes sit together, so one cache line can hold 64 useful values. The exact win depends on struct size and access pattern, but he reports up to 30x improvement when the struct grows to 1 KiB.
The random-access section is the sharper systems lesson. Sequential scans can benefit from prefetching, but pointer chasing through hash maps, trees, graphs, or other unpredictable structures cannot. Then total working-set size decides which cache tier you hit. Doubling objects from 64B to 128B can push the same number of elements from L1 into L2, or from L2 into L3, much earlier.
Newsletter angle: Useful performance material: sometimes the optimization is not a different algorithm, it is fewer bytes, tighter hot fields, and keeping the working set inside the next cache boundary.