Memory usage analysis
Recipe | Crates | Categories |
---|---|---|
Profile heap memory |
Profile heap memory
dhat
⮳ is a library for heap profiling and ad-hoc profiling with DHAT.
// `dhat` provides heap profiling and ad-hoc profiling capabilities to Rust, // similar to those provided by `DHAT`, a powerful heap profiler that // comes with `Valgrind`. Warning: This crate is experimental. // First, add to your `Cargo.toml`: // [dependencies] // dhat = "0.3.3" // // # You should only use `dhat` in release builds. // [profile.release] // debug = 1 // // # Create features that lets you easily switch profiling on and off: // [features] // dhat-heap = [] # if you are doing heap profiling // dhat-ad-hoc = [] # if you are doing ad hoc profiling // The heap profiling works by using a global allocator that wraps the system // allocator and tracks all heap allocations. // We set `dhat::Alloc` as the global allocator // using the #[global_allocator] attribute. #[global_allocator] static ALLOC: dhat::Alloc = dhat::Alloc; // When you run the code below with: // cargo run --features dhat-heap // `dhat` will collect heap profiling information. // The profiling data will be saved in a file named `dhat-heap.json` // in the current directory. You can then use e.g. // https://nnethercote.github.io/dh_view/dh_view.html // to analyze the profiling data. // The profiler also prints to `stderr`, like: // dhat: Total: 9,200 bytes in 10 blocks (note: "block" = allocation) // dhat: At t-gmax: 5,120 bytes in 2 blocks // dhat: At t-end: 1,024 bytes in 1 blocks fn heap_profiling() { // Start the heap profiling session #[cfg(feature = "dhat-heap")] let _profiler = dhat::Profiler::new_heap(); // Example code to profile: // Create a vector and pushes 1000 elements into it. let mut vec = Vec::new(); for i in 0..1000 { vec.push(i); } #[cfg(feature = "dhat-heap")] println!("Memory profiling complete!"); } // Ad hoc profiling involves manually annotating hot code points. // Run with: cargo run --features dhat-ad-hoc // The profiler prints to `stderr`: // dhat: Total: 100,000 units in 100,000 events // dhat: The data has been saved to dhat-ad-hoc.json, and is viewable with // dhat/dh_view.html fn adhoc_profiling() { #[cfg(feature = "dhat-ad-hoc")] let _profiler = dhat::Profiler::new_ad_hoc(); fn hot_function() { #[cfg(feature = "dhat-ad-hoc")] dhat::ad_hoc_event(1); } for _ in 0..100000 { hot_function(); } } pub fn main() { heap_profiling(); adhoc_profiling(); } // `dhat` also supports heap usage testing, where you can write tests and then // check that they allocated as much heap memory as you expected. #[test] fn heap_usage_testing() { // `testing()` allows the use of dhat::assert! and related macros, // and disables saving of profile data on Profiler drop. let _profiler = dhat::Profiler::builder().testing().build(); let _v1: Vec<i32> = vec![1, 2, 3, 4]; let v2: Vec<u8> = vec![5, 6, 7, 8]; drop(v2); let stats = dhat::HeapStats::get(); // Total allocations and number of bytes: // dhat::assert_eq!(stats.total_blocks, 2); dhat::assert_eq!(stats.total_bytes, 20); // Allocations and number of bytes at the point of peak heap size: // dhat::assert_eq!(stats.max_blocks, 2); dhat::assert_eq!(stats.max_bytes, 20); // Now a single allocation remains alive. // dhat::assert_eq!(stats.curr_blocks, 1); dhat::assert_eq!(stats.curr_bytes, 16); } // Example adapted from https://docs.rs/dhat/latest/dhat/
Memory Profiling (Allocation Tracking)
valgrind
⮳ (with massif
or memcheck
): While not Rust-specific, Valgrind is a very common and powerful memory profiler. You'd run your Rust program under Valgrind.
heaptrack
⮳: A heap profiler that can track memory allocations.
Leak Detection
valgrind
⮳ (with memcheck
): Excellent for detecting memory leaks.
Address Sanitizer (ASan
): Often integrated into the compiler; can detect memory leaks and other memory errors. Enable it with compiler flags (e.g., -fsanitize=address
).
Memory Usage Analysis (for specific regions)
measure_time
⮳: While not strictly a memory profiler, it can help you measure the execution time of code blocks, which can be useful when investigating memory-related performance issues.
Debugging Tools (for examining memory)
gdb
⮳, lldb
⮳: Debuggers can be used to inspect memory, examine variables, and track allocations.
Tracing (for understanding allocation patterns):
tracing
⮳: While not a direct memory profiler, tracing can help you understand the flow of your program and identify areas where excessive allocations might be occurring.
Heap Inspection Tools
heapdump
: A tool for creating heap dumps of running processes, which can then be analyzed with other tools.
<
/div>