Course contentsShow
← Rust
Lesson 1353 of 1,91011. Asynchronous ProgrammingFree lesson

Async Memory Alignment Optimization

Ensure cache-line alignment of shared state structures to prevent false sharing in multi-core executors.

In this lesson, you will learn how to prevent "false sharing" in multi-core asynchronous executors by aligning your shared state structures to CPU cache lines.

The Problem: False Sharing

In a high-performance asynchronous runtime, your tasks are often distributed across multiple CPU cores. When two independent variables reside on the same 64-byte cache line, the CPU hardware treats them as a single unit. If Core A modifies variable X while Core B modifies variable Y, the cache coherency protocol forces the cores to repeatedly synchronize the entire cache line. This "ping-ponging" effect is called false sharing; it destroys performance because it forces threads to wait on memory hardware arbitration rather than executing your async code.

The Solution: Cache-Line Alignment

To prevent this, we must ensure that frequently mutated shared states—such as atomic counters or task status flags—are padded so they occupy their own dedicated cache lines. In Rust, we use the #[repr(align(64))] attribute to force the compiler to place the start of a structure on a 64-byte boundary (the standard cache line size for x86_64 and ARM64).

Implementation Example

Consider a shared metrics structure used by multiple async tasks:

#[repr(align(64))]
struct SharedCounter {
    value: std::sync::atomic::AtomicU64,
}

// Even if these are placed next to each other in memory,
// the alignment ensures they sit on different cache lines.
struct Metrics {
    reads: SharedCounter,
    writes: SharedCounter,
}

By adding #[repr(align(64))], we guarantee that reads and writes do not share a cache line. Even if a thread on Core 1 increments reads and a thread on Core 2 increments writes, the CPU can perform these operations independently without triggering cross-core cache invalidations.

When designing shared state for async executors, always identify structures that undergo high-frequency concurrent writes. If those structures are small, they are likely victims of false sharing. Wrapping them in an aligned struct is a low-overhead way to scale your throughput linearly as you add more CPU cores to your runtime.

Key Takeaway: Use #[repr(align(64))] on shared asynchronous state to prevent false sharing and ensure that high-frequency concurrent mutations occur on independent cache lines.