In this lesson, you will learn how to optimize memory usage by packing multiple boolean flags into a single byte using bitwise manipulation.
The Cost of Booleans
In Rust, a bool occupies one full byte of memory to ensure that every addressable value has a unique memory location. If you have a struct containing eight distinct flags—like is_active, is_admin, is_readonly, and so on—Rust will allocate 8 bytes. For high-performance systems or massive collections, this overhead adds up quickly.
Bitwise Packing
Instead of using eight bytes, we can use a single u8 (an unsigned 8-bit integer) and treat each individual bit as a flag. By using the bitwise OR (|) operator to set a flag and the bitwise AND (&) combined with the NOT (!) operator to clear it, we gain granular control over the data.
Consider this implementation:
struct Permissions(u8);
impl Permissions {
const READ: u8 = 1 << 0; // 00000001
const WRITE: u8 = 1 << 1; // 00000010
const EXEC: u8 = 1 << 2; // 00000100
fn set_read(&mut self) { self.0 |= Self::READ; }
fn is_read(&self) -> bool { (self.0 & Self::READ) != 0 }
fn clear_read(&mut self) { self.0 &= !Self::READ; }
}
How It Works
- The Bit Mask: We define constants using the bit-shift operator (
1 << n). This creates a value where only the n-th bit is set to 1. - Setting: The
|=operator forces a specific bit to1without affecting other bits. - Checking: The
&operator masks the byte. If the result is non-zero, the flag is set. - Clearing: The
!Self::READcreates a mask where every bit except the one we want to clear is1. Applying&ensures the target bit becomes0while preserving the state of all other flags.
By using this technique, we reduce the memory footprint by 8x for boolean collections, significantly improving cache locality when processing thousands of instances. This is a common pattern in low-level drivers, protocol parsers, and game engines where every byte saved increases the system's overall throughput.
Key Takeaway: Bitwise manipulation allows you to trade a small amount of CPU overhead for a significant reduction in memory footprint by treating individual bits as boolean storage.