Why is Vec<(u64,u64)> using that much memory?

165 points randomusr0815 73 comments
use rand::prelude::*;
fn main() {
    let mut rng = rand::rng();
    let mut v : Vec<(u64,u64)> = Vec::with_capacity(100000000);
    // use 2*8*100000000 = 1,600,000,000 bytes of memory
    for _ in 0..100000000 {
        let a = rng.random_range(0..123456789);
        let b = rng.random_range(0..123456789);
        v.push((a,b));
    }
    v.sort_by_key(|a| a.0);
    // avoid optimizing out
    println!("{:?}", v[13]);
}

When I run this minimal example with /usr/bin/time -v target/release/example, then it tells me that it has used a maximum resident set size of 2345696kB or approximately 2.23GiB when it should only have used around 1.5GiB. Of course, some overhead with cargo etc., but this does not explain hundreds of megabytes more than the size of the Vec should have been.

What is going on? Is there some aligning going on with tuples? Is it the sorting algorithm? Unfortunately, I need to optimize this as I have a very large vec with two u64 pairs which needs to be sorted and is almost the size of my available RAM, so I cannot "waste" this much.