Course contentsShow
← Rust
Lesson 793 of 1,9106. Generics and Static DispatchFree lesson

Generic Code in Embedded Environments

Optimize memory-limited code paths by choosing generic structures that favor stack allocation.

In this lesson, you will learn how to leverage static dispatch in generic structures to keep your embedded memory footprint minimal by favoring stack allocation over heap alternatives.

The Cost of Flexibility

In resource-constrained embedded environments, every byte of RAM counts. When we write generic code, Rust performs monomorphization—it generates a specific copy of your function or struct for every unique type you use. While this is great for performance, it can lead to "code bloat." However, the real memory danger in embedded systems often comes from using dynamic dispatch (like Box<dyn Trait>) which forces data onto the heap.

By using generics with static dispatch, we can keep our structures on the stack and ensure the compiler knows the exact size of our data at compile time.

Static Allocation with Generics

Consider a sensor buffer. If we use a dynamic approach, we might be tempted to use a vector, but that requires an allocator, which many embedded systems lack. Instead, we can use a generic struct that holds a fixed-size array:

struct SensorBuffer<T, const N: usize> {
    data: [T; N],
}

impl<T: Copy + Default, const N: usize> SensorBuffer<T, N> {
    fn new() -> Self {
        Self { data: [T::default(); N] }
    }
}

By using the const generic N, the compiler creates a concrete version of SensorBuffer where the size is known. Because the size is fixed at compile time, the entire struct is placed on the stack. There is no heap allocation, no pointer chasing, and the memory usage is perfectly predictable.

Why This Matters

When you use trait objects (dyn Trait), the compiler must include a vtable (virtual method table) in your binary, and the data is often moved to the heap. With static dispatch using generics, the compiler inlines the method calls directly. This not only saves precious RAM but often results in smaller binary sizes because the compiler can prune unused branches of your code that are never called with a specific type.

Key Takeaway: Use generic structures with constant sizing to move memory allocation from the heap to the stack, ensuring your embedded application remains predictable, memory-safe, and efficient.