Under the hood: Vec<T>

marma.dev

173 points by r4um 7 days ago


jojomodding - 3 days ago

The explanation of `Unique` is a bit botched. `Unique` was originally intended to convey uniqueness in the sense of `noalias`, so that more compiler optimizations are possible similar to what happens around mutable references. This is what the article seems to suggest is going on .

But this is wrong, it is no longer the case that `Unique` implies any extra optimizations, since it was since recognized that having these optimizations on a low-level unsafe building block is actually undesirable. Further, the `as_ref` functions mentioned in the article are not used by `Vec`'s internals. They are anyways only marked unsafe because they create references, not because of anything special with `Unique`.

Nowadays, all that `Unique` does is interact with `dropck` in a quirky way, the "exception to the exception." It is quite complicated and I always have to read up on it. It is explained in the Rustonomocon, in the "Click here to see why" section of this chapter: https://doc.rust-lang.org/nomicon/phantom-data.html#an-excep...

tialaramex - 4 days ago

Because this is focused on how the data structure works it doesn't mention lots of nice API design choices in Rust.

The one I particularly want to call out because it came up this morning is providing both Vec::reserve and Vec::reserve_exact

Vec::reserve lets us hint about our upcoming capacity expectations without damaging the O(1) amortized growth which is the whole point of this collection type, but it can waste some memory to achieve this. This is probably what you want in most code.

Vec::reserve_exact is a more narrow idea - we can hint about the ultimate capacity needed, if we're wrong and later need more capacity this has a significant performance cost because we thew away the amortized growth promise to get this, but we don't waste memory.

C++ only provides the equivalent of Vec::reserve_exact which makes this a footgun but if you use this call when you really needed the other one you trash your perf, as a result of which people teaching C++ tend to just say don't use reservation to uh, reserve capacity, but now you're leaving perf on the table so that's not great.

veber-alex - 4 days ago

This article feels too long and rambly considering how little actual technical information it provides.

sedatk - 3 days ago

> Since a NonNull<T> can never be null, the compiler knows it can use the 0 address to represent the None variant when it sees an Option<NonNull<T>>

I didn't know this about Rust. That's awesome.

5- - 4 days ago

related: https://doc.rust-lang.org/nomicon/vec/vec.html