notes/systems
← index

Cache line false sharing, measured

Two threads writing to two different variables should not contend. If those variables share a 64-byte cache line, they do.

What it looks like

Throughput that gets worse as you add cores. Not flat — worse. That shape is nearly diagnostic on its own; almost nothing else degrades with added parallelism the way false sharing does.

perf stat -e cache-misses,cache-references \
          -e LLC-load-misses ./bench

Confirming it

perf c2c exists for exactly this and is worth learning:

perf c2c record ./bench
perf c2c report --stdio

It reports HITM events — loads that hit a line modified in another core's cache. That is the actual signature, not a general rise in cache misses.

The fix is boring

Pad the structure so contended fields land on separate lines.

struct counter {
    _Atomic long value;
    char pad[64 - sizeof(_Atomic long)];
} __attribute__((aligned(64)));

Measure first. Padding everything wastes cache and will make some workloads slower, and the version of this bug people imagine is far more common than the version that is really there.