Course contentsShow
← Rust
Lesson 1721 of 1,91015. Performance and Architectural EngineeringFree lesson

Preventing False Sharing

Avoid performance degradation caused by multiple threads updating fields on the same cache line.

In this lesson, you will learn how to identify and prevent performance bottlenecks caused by "false sharing" in multi-threaded Rust applications.

Understanding the Cache Line Problem

Modern CPUs do not fetch individual bytes from main memory; they fetch data in fixed-size chunks called cache lines (typically 64 bytes). When a thread modifies data, the CPU marks the entire cache line as "modified" to ensure consistency across cores via the cache coherency protocol (like MESI).

False sharing occurs when two or more threads update independent variables that happen to reside on the same cache line. Even though the variables are logically separate, the CPU's coherency hardware sees them as a single unit. As Core A modifies its variable, it effectively invalidates the cache line for Core B, forcing Core B to reload the data from memory. This results in "ping-ponging" the cache line between cores, destroying your parallel scaling.

Detecting and Fixing False Sharing

Consider a struct where you track separate counters for different threads:

struct Counter {
    thread_a: AtomicU64,
    thread_b: AtomicU64,
}

If thread_a and thread_b are frequently updated simultaneously, they will likely sit on the same 64-byte cache line. To prevent this, we use the #[repr(align(64))] attribute or padding to force the variables onto separate cache lines.

#[repr(align(64))]
struct PaddedAtomic(AtomicU64);

struct Counter {
    thread_a: PaddedAtomic,
    thread_b: PaddedAtomic,
}

By ensuring each AtomicU64 starts on a new cache line boundary, you guarantee that an update to thread_a does not invalidate the cache line containing thread_b. This eliminates unnecessary synchronization overhead and allows your threads to operate at full hardware speed.

When to Apply This

You should only apply this technique to hot paths where contention is proven through performance profiling. Adding alignment padding increases the memory footprint of your data structures and can decrease cache density, so it is a trade-off between memory efficiency and raw execution speed.

Key Takeaway: To prevent false sharing, isolate highly contended, concurrently accessed variables onto their own cache lines using #[repr(align(N))] to ensure they do not reside on the same hardware cache unit.