-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Box::new copies generated Future unless call is wrapped #100932
Comments
moves are actually implemented as |
Thanks for this, I've been looking for small examples where |
For more, see #49733 |
Yeah it seems like a Rust best practice is to always work with smallish structs and basically assume everything might get copied when moved, and hope that such copying won't be meaningful. Unfortunately, generated futures often make working with big structs unavoidable. Interestingly, I discovered this issue while attempting to avoid moving futures. Most runtime spawn functions (for example, tokio::spawn) are generic and take a non-boxed value (i.e. they have a signature like It is really counterintuitive because you'd think immediately boxing a future would be a good best practice, i.e. it would be the best chance of avoiding copies, when actually immediate boxing risks adding a copy. Passing the future by value to a function that then boxes the value is how you save the copy. |
On nightly with |
The memcpy is still present for me with EDIT: sorry, that was on stable. On nightly I can confirm that |
Generally, optimizers employ a large amount of heuristics which are unreliable. It's not uncommon that something like this causes changes in their output.
If I had to guess, I would point at the LLVM 15 upgrade (#99464). LLVM keeps changing their optimizer all the time so it's possible that it now detects this case, whether unintentionally or not. |
@rustbot label +A-async-await |
opt-level=3 can be quite aggressive, and I think we should be able to optimize this away at opt-level=2 at least. |
Do we know that opt-level=2 doesn't catch this on nightly still? If there was an LLVM upgrade, maybe that caught this case as well. |
We talked about this in the wg-async triage meeting. It sounds like this is a more general bug that async code happens to be more likely to expose, so we'll remove the async label. @rustbot label -A-async-await |
opt-level=2 on nightly does not catch it |
I've confirmed this issue is fixed in 1.65.0-beta.1 (2a65764 2022-09-19). |
And... confirmed the fix made it to stable! (1.65.0) |
Sometimes boxing a generated Future causes the value to be (unnecessarily?) copied. This can be worked around by wrapping the call to
Box::new
.Code:
Asm contains a ~16k memcpy:
In main, if you comment out the first line and uncomment the second, the memcpy goes away, even though the code is nearly identical. I'd expect both ways to compile down the same.
Box::pin
is similarly affected.The behavior is present in the latest stable and nightly.
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: