In this lesson, you will learn how to look under the hood of your Rust program to see exactly how much memory it is allocating and whether those allocations are being cleaned up correctly.
Why Profile Memory?
Even with Rust’s powerful ownership model, you can still encounter scenarios where memory usage grows unexpectedly. This usually happens when long-running programs accumulate data in heap-allocated collections (like Vec or HashMap) that are never dropped. Profiling helps you visualize these "memory leaks" or inefficient allocation patterns.
Using Heap Profilers
While we use GDB or LLDB to inspect the state of a program at a single moment, a heap profiler tracks every allocation and deallocation throughout the program’s execution.
A popular tool in the Rust ecosystem is DHAT (part of the Valgrind suite). You don't usually need to change your code to use it; instead, you run your compiled binary through the profiler.
Imagine you have a simple loop that unintentionally pushes items into a Vec inside a loop:
fn main() {
let mut data = Vec::new();
loop {
// Suppose we forget to clear this or move it out of scope
data.push(vec![0u8; 1024]);
if data.len() > 1000 { break; }
}
}
When you run this under a profiler like DHAT, it captures a "trace." After the program finishes, the tool generates a report showing:
- Total bytes allocated: The sum of every request for memory.
- Maximum residency: The peak amount of RAM your program held at any one time.
- Leaks: Memory that was still allocated when the program terminated.
How to Interpret the Data
When you look at the profiler output, focus on the "Top Call Sites." These are the specific lines in your code that requested the most memory. If you see a function appearing at the top of the list that you didn't expect to be memory-heavy, that is your signal to investigate. You might find that you are cloning large structs unnecessarily or holding onto references longer than needed.
Key Takeaway: Memory profiling transforms "invisible" heap growth into actionable data, allowing you to identify exactly which lines of code are driving your program’s peak RAM usage.