Any advantage of Box<[[[u64; 16]; 16]; 16]> over Vec<u64>?

Initially, I thought Box<[[[u64; 16]; 16]; 16]> is nice because we know statically the dimensions, and maybe the compiler can do some magic optimizations.

However, in terms of indexing, it seems Box<> has the same amount of indirection as Vec<>, and with Box, there is always this fear I might accidentally overflow the stack in constructors.

Does Box have any advantage over Vec in the above ?

One minor advantage of Box<[T]> over Vec<T> is that it does not store capacity, thus it has size of 2 words instead of 3.

As for using [[[u64; 16]; 16]; 16] instead of u64, I would say it improves indexing code, i.e. foo[i][x][y][z] is better and less error-prone than foo[16*16*16*i + 16*16*x + 16*y + z]. For example, the latter may not result in panic if x, y, or z is bigger or equal to 16.

UPD: I've misread the OP and thought the author meant Box<[[[[u64; 16]; 16]; 16]]>, i.e. boxed slice instead of boxed array.

Well, remember you can always create such a box via a vector.

For example, you could do this:

pub fn demo() -> Box<[[[u64; 16]; 16]; 16]> {
    let v = vec![Default::default(); 16];
    v.into_boxed_slice().try_into().unwrap()
}

Which you can see on godbolt doesn't put anything on the stack, and only fails if the allocation fails. It's just __rust_alloc+memset:

example::demo:
        push    rbx
        mov     edi, 32768
        mov     esi, 8
        call    qword ptr [rip + __rust_alloc@GOTPCREL]
        test    rax, rax
        je      .LBB0_1
        mov     rbx, rax
        mov     edx, 32768
        mov     rdi, rax
        xor     esi, esi
        call    qword ptr [rip + memset@GOTPCREL]
        mov     rax, rbx
        pop     rbx
        ret
.LBB0_1:
        mov     edi, 32768
        mov     esi, 8
        call    qword ptr [rip + alloc::alloc::handle_alloc_error@GOTPCREL]
        ud2

EDIT: And here's a PR so it can be just __rust_alloc_zeroed instead of the separate memset: Support arrays of zeros in Vec's __rust_alloc_zeroed optimization by scottmcm · Pull Request #95362 · rust-lang/rust · GitHub

4 Likes

And Box<[T; N]> that's used here has a size of 1 word.

7 Likes