Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad exemple / Misleading use of Box::new in 4.1. What is Ownership #165

Open
Ily3s opened this issue Mar 1, 2024 · 1 comment
Open

Bad exemple / Misleading use of Box::new in 4.1. What is Ownership #165

Ily3s opened this issue Mar 1, 2024 · 1 comment

Comments

@Ily3s
Copy link

Ily3s commented Mar 1, 2024

https://rust-book.cs.brown.edu/ch04-01-what-is-ownership.html#boxes-live-in-the-heap

Here it introduces to boxes by showing us how we can move an array of 1 million integers from a variable a to a variable b. It suggests that doing that using boxes is more efficient than just doing a copy on the stack because moving a box doesn't actually do a copy.

The problem is this following line of code : let a = Box::new([0; 1_000_000]);. Looking at its assembly output, I discovered this actually sets 4 million bytes to zero on the stack before allocating 4MB on the heap and then actually performing a copy ! This happens only on debug mode. In release mode however, it doesn't happen only because the value we're assigning every integer of the array to is 0, but with anything else than 0, it does pretty much the same thing as in debug.

Since I'm never certain of what I understand from assembly, I verified this by replacing the value of 1 million by 10 millions, which as I expected, caused a stack overflow !

This means that the solution with Box is effectively worse than the one with just a raw copy on the stack. I find that to be pretty misleading since it's shown as being the solution to avoid copying, whereas, not only does it copies, but it copies from the stack to the heap (which is worse than a stack to stack copy). I think this should be done using vec! instead.

Edit: When I think about it I realise this moving over copying issue might just be a memory issue rather than a performance issue since allocating on the heap is probabely always slower anyway.
Still I think it is relevant to point at the fact that with Box::new, at some point, 4MB are pushed onto the stack, which could be avoided with the use of vec!

@willcrichton
Copy link
Collaborator

To be clear, it only copies from the stack to the heap when constructing the box. Once the heap object is prepared, then pointers to it can be freely copied with no cost.

You're right that the stack-to-heap copy can be expensive. Rust does not have C++'s concept of "placement new", but not for lack of trying. See: rust-lang/rust#27779 (comment)

I will probably keep the book the same because the example still satisfies its intended purpose: showing the difference in behavior of copies between owned and boxed arrays.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants