Course contentsShow
← Rust
Lesson 170 of 1,9102. The Ownership ModelFree lesson

Memory Footprint Optimization

Use bit-packing and niche optimizations to reduce the memory size of structures.

In this lesson, you will learn how to shrink the memory footprint of your data structures by utilizing bit-packing and Rust’s "niche" optimization system.

The Cost of Padding

When you define a struct, Rust aligns its fields to specific memory boundaries to ensure the CPU can access them efficiently. Often, this results in "padding"—invisible bytes of wasted space inserted between fields to satisfy alignment requirements. Furthermore, types like bool or u8 consume an entire byte, even though they only need a fraction of that space.

Bit-Packing

If you have a group of small flags, you don't need a bool for each one (which costs 1 byte per flag). Instead, you can "pack" them into a single integer. By using bitwise operators, you can store eight boolean flags inside a single u8.

struct Flags {
    // We use a single byte to store 8 individual boolean states
    bits: u8,
}

impl Flags {
    fn set_active(&mut self) { self.bits |= 1 << 0; }
    fn is_active(&self) -> bool { (self.bits & 1 << 0) != 0 }
}

Leveraging Niches

Rust has a clever feature called "niches." A niche is a bit pattern in a type that is invalid. For example, a NonZeroU32 cannot be 0. Rust realizes that 0 is an unused state, so it uses that "niche" to store the None variant of an Option<NonZeroU32> without increasing the size of the structure.

Normally, an Option<u32> takes 8 bytes (4 for the u32 and 4 for the discriminant tag). However, Option<NonZeroU32> takes only 4 bytes because it "steals" the 0 bit pattern to represent None.

Why this matters

By reordering fields to minimize padding and using types that exploit niches, you can significantly reduce the memory footprint of your structs. When you are working with millions of objects in memory, these small savings prevent cache misses and reduce the overall pressure on your system's RAM.

Key Takeaway: By packing booleans into bitfields and choosing types that allow Rust to hide metadata in "niche" bit patterns, you can drastically reduce struct size and improve cache locality.