Live data from Hacker News

Under the hood: Vec

marma.dev

51–60 of 142 posts

Re: Under the hood: Vec<T>

#51

I'm sure all these layers are good engineering and provide meaningful safety guarantees, but it sure makes the code harder to understand if you want to see how things are implemented. Another example, I was trying to see how i64::isqrt is implemented, but first you have to wade through layers of macros

This is just how rust and c++ code is in my experience.

C++ is bc of compatibility with god knows how many standards, but at the end it is simpler than it looks at first sight. The uglification of names in the std lib make it disgusting to read. If only that was removed it would improve a lot.

Re: Under the hood: Vec<T>

#52
post #20
post #7

While safe Rust may be relatively simple to write, and certainly easier to write than safe C, this article has someone added to my belief that unsafe Rust is far too difficult to write. Perhaps some of this is deliberate, as a kind of defence mechanism against people using it willy-nilly, it still seems over-designed.

I think most of the complexity here comes from trying to write as little unsafe code as possible (and not repeating any unsafe operation in multiple places, hence the many layered abstractions). If you were to implement Vec without layering, it would be no more complicated than writing a dynamic array in C (but more verbose due to all the unsafe blocks and unabbreviated names)

Notably, some of the abstraction is actually there to prevent the compiler from generating a lot of redundant code. The process of monomorphization (turning polymorphic generic code into usable machine code for particular types) can seriously bloat the size of binaries.

Re: Under the hood: Vec<T>

#53

Earlier quoted context omitted.

From your description, I cannot determine the difference. Engineers like exact things, whats this fuzzy concept called “hint”?

Suppose I think I may need 128 entries at some point, but the vector is allocated with room for 16 entries by default. I may not want to allocate and then immediately allocate again. But if I get to a 17th entry then I’m already causing allocation. So I might as well allocate 128 at that time so there are no more allocations at all.

All the functions mentioned above, even the cpp one, will reserve atleast the number of elements given to resize() or resize_exact(), but may reserve more than that.

After some pondering, and reading the rust documentation, I came to the conclusion that te difference is this: reserve() will grow the underlaying memory area to the next increment, or more than one increment, while reserve_exact() will only grow the underlaying memory area to the next increment, but no more than that.

Eg, if grow strategy is powers of two, and we are at pow(2), then reserve() may skip from pow(2) to pow(4), but reserve_exact() would be constrained to pow(3) as the next increment.

Or so i read the documentation. Hopefully someone can confirm?

Re: Under the hood: Vec<T>

#54
post #22
post #9

Earlier quoted context omitted.

I come from a Swift/Kotlin background and I've been learning Rust for fun in my spare time From what I heard online I was expecting it to be a lot harder to understand! The moving/borrowing/stack/heap stuff isn't simple by any means, and I'm sure as I go it will get even harder, but it's just not as daunting as I'd expected It helps that I love compiler errors and Rust is full of them :D Every error the compiler catc…

The language and associated tooling keep improving. Over the course of the last decade I've made several attempts to learn Rust, but was always frustrated with having code that reasonably should compile, but didn't and I had to run the build to even find that out. Now we have rust-analyzer and non-lexical lifetimes, both tremendously improving the overall experience. I still don't enjoy the fact that borrows are at t…

Rust is not the most productive language by any means... it is hardened AF if you avoid unsafe, but productive?

I can code much faster in almost any language compared to Rust. It creates mental overhead. For example, to compare it to siblings, Swift and C++ (yes, even C++, but with a bit of knowledge of good practices) lets you produce stuff more easily than Rust.

It is just that Rust, compared to C++, comes extra-hardened. But now go get refactor your Rust code if you started to add lifetimes around... things get coupled quickly. It is particularly good at hardening and particularly bad at prototyping.

They seem to be the opposite in the absence of borrowing without a garbage collector, since you need to mark the lifetime in some way.

Re: Under the hood: Vec<T>

#55
post #9

Earlier quoted context omitted.

I come from a Swift/Kotlin background and I've been learning Rust for fun in my spare time From what I heard online I was expecting it to be a lot harder to understand! The moving/borrowing/stack/heap stuff isn't simple by any means, and I'm sure as I go it will get even harder, but it's just not as daunting as I'd expected It helps that I love compiler errors and Rust is full of them :D Every error the compiler catc…

> It helps that I love compiler errors and Rust is full of them :D Every error the compiler catches is an error my QA/users don't amen! I despise Python even though I used to love it, and that's because it's full of runtime errors and unchecked exceptions. The very instant I learned more strongly typed languages, I decided never to go back.

Python properly paired with typing is very competent IMHO.

Re: Under the hood: Vec<T>

#56

Earlier quoted context omitted.

From your description, I cannot determine the difference. Engineers like exact things, whats this fuzzy concept called “hint”?

The difference according to Rust doc itsef: reserve() > Reserves capacity for at least additional more elements to be inserted in the given Vec . The collection may reserve more space to speculatively avoid frequent reallocations. reserve_exact() > Reserves the minimum capacity for at least additional more elements to be inserted in the given Vec . Unlike reserve, this will not deliberately over-allocate to speculati…

[deleted]

Re: Under the hood: Vec<T>

#57
post #37

Earlier quoted context omitted.

It's not particularly easy to teach what that actually means and why it's a thing. It's quite easy to show why in general G cannot be a subtype of G even if A is a subtype of B, it's rather more involved pedagogically to explain when it can , and even more confusing when it's actually the other way around (contravariance). Anyway, Rust has no subtyping except for lifetimes ('a <: 'b iff 'a lasts at least as long as '…

I’m getting old. I can understand the words, but not the content. At this point, show me dissassembly so that I can understand what actually happens on the fundamental byte/cpu instruction level, then I can figure out what you’re trying to explain.

Nothing really happens on the instruction level because this is all type system logic.

Re: Under the hood: Vec<T>

#58
post #22

Earlier quoted context omitted.

The language and associated tooling keep improving. Over the course of the last decade I've made several attempts to learn Rust, but was always frustrated with having code that reasonably should compile, but didn't and I had to run the build to even find that out. Now we have rust-analyzer and non-lexical lifetimes, both tremendously improving the overall experience. I still don't enjoy the fact that borrows are at t…

Rust is not the most productive language by any means... it is hardened AF if you avoid unsafe, but productive? I can code much faster in almost any language compared to Rust. It creates mental overhead. For example, to compare it to siblings, Swift and C++ (yes, even C++, but with a bit of knowledge of good practices) lets you produce stuff more easily than Rust. It is just that Rust, compared to C++, comes extra-ha…

Rust is not that bad at prototyping, you need to use the right featureset when writing quick prototype code. Don't use lifetimes, use clone() and Rc/Arc freely to get around borrow-checker issues. Use .unwrap() or .expect("etc.") whenever you're not sure how to pass an error back to the caller. Experiment with the "Any" trait for dynamic typing and downcasts, etc. The final code will still be very high-performance for prototype code, and you can use the added boilerplate to guide a refactoring into a "proper" implementation once the design stabilizes.

Re: Under the hood: Vec<T>

#59

Can anyone compare it to C++ in terms of memory layout for typical implementations?

The vector implementation on my machine uses three pointers: start, end, and end-of-storage. It's basically the same, but uses addresses rather than counts. The valarray implementation uses a pointer and a single count.

Re: Under the hood: Vec<T>

#60

Can anyone compare it to C++ in terms of memory layout for typical implementations?

That's one of major problems I have with Rust docs and community. The best way to explain most things in Rust to experienced dev, is by comparison to C++. But all the docs and blog posts explicitly target newbies and avoid comparison with C++ at all cost.
Post reply on HN