There are several questions already on Stack Overflow about allocating an array (say [i32]
) on the heap. The general recommendation is boxing, e.g. Box<[i32]>
. But while boxing works fine enough for smaller arrays, the problem is that the array being boxed has to first be allocated on the stack.
So if the array is too large (say 10 million elements), you will - even with boxing - get a stack overflow (one is unlikely to have a stack that large).
The suggestion then is using Vec<T>
instead, that is Vec<i32>
in our example. And while that does do the job, it does have a performance impact.
Consider the following program:
fn main() {
const LENGTH: usize = 10_000;
let mut a: [i32; LENGTH] = [0; LENGTH];
for j in 0..LENGTH {
for i in 0..LENGTH {
a[i] = j as i32;
}
}
}
time
tells me that this program takes about 2.9 seconds to run. I use 10'000 in this example, so I can allocate that on the stack, but I really want one with 10 million.
Now consider the same program but with Vec<T>
instead:
fn main() {
const LENGTH: usize = 10_000;
let mut a: Vec<i32> = vec![0; LENGTH];
for j in 0..LENGTH {
for i in 0..LENGTH {
a[i] = j as i32;
}
}
}
time
tells me that this program takes about 5 seconds to run. Now time
isn't super exact, but the difference of about 2 seconds for such a simple program is not an insignificant impact.
Storage is storage, the program with array is just as fast when the array is boxed. So it's not the heap slowing the Vec<T>
version down, but the Vec<T>
structure itself.
I also tried with a HashMap
(specifically HashMap<usize, i32>
to mimic an array structure), but that's far slower than the Vec<T>
solution.
If my LENGTH
had been 10 million, the first version wouldn't even have run.
If that's not possible, is there a structure that behaves like an array (and Vec<T>
) on the heap, but can match the speed and performance of an array?