Why does creating a very large vector of zero sized items take forever while an array is fine?

Viewed 82

This code runs fine:

use std::mem::size_of;

fn main() {
    println!("{}", size_of::<[(); usize::max_value()]>());
    let x = [(); usize::max_value()];
    println!("done");
}

It immediately prints 0 and done. The array is 0 bytes large after all, so this is expected.

If I use a Vec however, things look different:

fn main() {
    let x = vec![(); usize::max_value()];
    println!("done");
}

This runs a very long time and never prints done. Why is that? I also expect the vector to have 0 actual size. So it shouldn't need to allocate or write any memory. What is taking so long?

This only happens when I compile without optimizations. With optimizations, it finished immediately.

1 Answers

Your array expression [(); usize::max_value()] is understood and interpreted directly by the compiler. The vec![(); usize::max_value()] expression on the other hand is a macro. So let's see what it expands to!

Using cargo expand, I get:

let x = ::alloc::vec::from_elem((), usize::max_value());

You won't find this methods in the docs as it's doc(hidden). You can see it in the source here. It delegates to a trait to specialize for certain types for performance. In the () case, this impl is used. This mainly calls the private method extend_with, defined here.

And there we finally see the problem: a for _ in 1..n loop. Without optimizations, this loop isn't removed and thus, the program takes forever trying to perform usize::max_value() loop iterations.

Related