Course contentsShow
← Rust
Lesson 1196 of 1,91010. Concurrency PrimitivesFree lesson

Cache Line Padding for False Sharing

You will prevent performance degradation caused by cache-coherency traffic between cores.

In this lesson, you will learn how to prevent CPU cache-coherency bottlenecks by aligning data to prevent "False Sharing."

The Problem: Cache Line Contention

Modern CPUs don't fetch memory byte-by-byte; they fetch it in chunks called cache lines (typically 64 bytes). When a core modifies data in a cache line, the CPU marks that entire line as "dirty" in its local cache. Consequently, it sends a signal via the MESI protocol to invalidate that same cache line in the caches of all other cores.

False Sharing occurs when two independent variables—used by different threads—happen to reside on the same 64-byte cache line. Even if Thread A and Thread B are modifying completely different variables, the hardware sees them as competing for the same cache line. The CPU cores constantly bounce ownership of that line back and forth, forcing costly synchronization traffic that destroys performance.

The Solution: Padding

To fix this, we ensure that frequently mutated, independent variables reside on different cache lines by inserting "padding" bytes between them.

use std::sync::atomic::{AtomicU64, Ordering};

// Without padding, these two atomics often sit on the same cache line.
// Every time thread A updates 'count_a', thread B's cache line is invalidated.
struct SharedCounters {
    count_a: AtomicU64,
    // Add 56 bytes of padding to push count_b onto the next cache line (64 bytes total)
    _padding: [u64; 7], 
    count_b: AtomicU64,
}

In this example, count_a and count_b are now effectively isolated. Because they occupy different cache lines, the CPU can manage them independently without triggering cache-coherency traffic between cores, allowing both threads to progress at full speed.

In production Rust, manually calculating padding is error-prone because cache line sizes can vary by architecture. While crates like crossbeam-utils provide a CachePadded<T> wrapper to automate this, the principle remains the same: ensure high-frequency, independent state does not share the same 64-byte neighborhood.

Key Takeaway: False sharing occurs when independent data competes for the same cache line; prevent it by using padding to isolate variables onto their own distinct lines.