In this lesson, you will learn how to minimize memory footprint by sharing common, immutable state across thousands of objects using the Flyweight pattern.
The Problem: Redundant Data
When building systems like text editors or game engines, you often deal with thousands of entities that share identical properties. For example, if you are rendering a forest of 10,000 trees, storing the full geometric data (the "intrinsic state") for every single tree would quickly exhaust your memory.
The Flyweight Solution
The Flyweight pattern suggests splitting your data into two parts:
- Intrinsic State: Immutable, shared data that is identical across many instances (e.g., the complex 3D model of a pine tree).
- Extrinsic State: Unique data that varies per instance (e.g., the specific (x, y, z) coordinates of a single tree).
By moving the intrinsic state into a shared resource, you only store it once in memory.
Implementation in Rust
In Rust, we often implement this using std::rc::Rc or std::sync::Arc to allow multiple owners to reference the shared data safely without cloning it.
use std::rc::Rc;
struct TreeModel {
mesh: Vec<f32>, // Heavy data
texture: String, // Heavy data
}
struct Tree {
position: (f32, f32),
model: Rc<TreeModel>, // Shared reference
}
fn main() {
let pine_model = Rc::new(TreeModel {
mesh: vec![0.0; 1000],
texture: "pine.png".to_string()
});
let forest = vec![
Tree { position: (0.0, 0.0), model: pine_model.clone() },
Tree { position: (10.0, 5.0), model: pine_model.clone() },
];
}
In this example, both trees point to the same TreeModel in heap memory. The Rc::clone call does not copy the heavy mesh or texture data; it simply increments a reference count. This allows your Tree instances to remain lightweight while maintaining a type-safe identity that points to the correct shared configuration. By centralizing the intrinsic state, you ensure that any memory-heavy components are only instantiated once, regardless of how many individual entities you need to represent in your application.
Key Takeaway: Use shared references like Rc or Arc to store redundant intrinsic state in a central location, keeping your individual objects small and efficient.