Course contentsShow
← Rust
Lesson 1425 of 1,91012. Unsafe Rust and Low-Level AccessFree lesson

Managing Cache Line Alignment

You will pad data structures to align with CPU cache lines to prevent false sharing and improve throughput.

In this lesson, you will learn how to manually align data structures to CPU cache lines to eliminate performance degradation caused by false sharing.

The Problem: False Sharing

Modern CPUs cache memory in blocks, typically 64 bytes wide, known as "cache lines." When two threads frequently modify different variables that happen to reside on the same cache line, the CPU’s cache coherency protocol kicks in. It forces the cache line to be invalidated and synchronized between cores every time one thread writes to its variable, even though the threads are logically independent. This "false sharing" causes severe performance hits, effectively serializing your parallel code.

Using #[repr(align(N))]

To prevent this, we must ensure that high-contention data structures occupy their own cache lines. We can use the #[repr(align(64))] attribute on a struct to force the compiler to place the start of that struct on a 64-byte boundary.

Consider this example where we want to separate two atomic counters:

use std::sync::atomic::AtomicU64;

#[repr(align(64))]
struct PaddedCounter {
    value: AtomicU64,
}

struct ContentionManager {
    // These two counters are now guaranteed to be on different cache lines,
    // as each PaddedCounter is aligned to a 64-byte boundary.
    counter_a: PaddedCounter,
    counter_b: PaddedCounter,
}

By forcing the compiler to align each PaddedCounter to a 64-byte boundary, we ensure that counter_a and counter_b cannot share a cache line. Even if they are adjacent in memory, the padding added by the compiler will fill the gap until the next 64-byte threshold is reached.

A Note on Optimization

While #[repr(align(N))] is effective, it increases your memory footprint. You should only apply this technique to structures that are subject to heavy concurrent write access. Over-padding can lead to "cache pollution," where your data structures occupy more space than necessary, potentially reducing the overall effectiveness of your CPU's L1/L2 caches. Always profile your application to verify that the reduction in cache coherency traffic outweighs the overhead of the extra memory usage.

Key Takeaway: Use #[repr(align(64))] to force data structures onto separate cache lines, preventing false sharing and significantly improving throughput in multi-threaded environments.