memoryrustbenchmarking

How to benchmark memory usage of a function?


I notice that Rust's test has a benchmark mode that will measure execution time in ns/iter, but I could not find a way to measure memory usage.

How would I implement such a benchmark? Let us assume for the moment that I only care about heap memory at the moment (though stack usage would also certainly be interesting).

Edit: I found this issue which asks for the exact same thing.


Solution

  • You can use the jemalloc allocator to print the allocation statistics. For example,

    Cargo.toml:

    [package]
    name = "stackoverflow-30869007"
    version = "0.1.0"
    edition = "2018"
    
    [dependencies]
    jemallocator = "0.5"
    jemalloc-sys = {version = "0.5", features = ["stats"]}
    libc = "0.2"
    

    src/main.rs:

    use libc::{c_char, c_void};
    use std::ptr::{null, null_mut};
    
    #[global_allocator]
    static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
    
    extern "C" fn write_cb(_: *mut c_void, message: *const c_char) {
        print!("{}", String::from_utf8_lossy(unsafe {
            std::ffi::CStr::from_ptr(message as *const i8).to_bytes()
        }));
    }
    
    fn mem_print() {
        unsafe { jemalloc_sys::malloc_stats_print(Some(write_cb), null_mut(), null()) }
    }
    
    fn main() {
        mem_print();
        let _heap = Vec::<u8>::with_capacity (1024 * 128);
        mem_print();
    }
    

    In a single-threaded program that should allow you to get a good measurement of how much memory a structure takes. Just print the statistics before the structure is created and after and calculate the difference.

    (The "total:" of "allocated" in particular.)


    divan implements a custom allocator in order to measure the memory use in benchmarks.


    You can also use Valgrind (Massif) to get the heap profile. It works just like with any other C program. Make sure you have debug symbols enabled in the executable (e.g. using debug build or custom Cargo configuration). You can use, say, http://massiftool.sourceforge.net/ to analyse the generated heap profile.

    (I verified this to work on Debian Jessie, in a different setting your mileage may vary).

    (In order to use Rust with Valgrind you'll probably have to switch back to the system allocator).

    P.S. There is now also a better DHAT.


    jemalloc can be told to dump a memory profile. You can probably do this with the Rust FFI but I haven't investigated this route.