-
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
Optimize option clone #76552
Optimize option clone #76552
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
I fully expect some pushback for the weird inclusion of Range inside Option, and am happy to pursue alternatives. I consider this PR as a jumping-off point for discussion for how to improve Option::clone's codegen, especially around Option<Range>. |
bebfcfd
to
f412124
Compare
cc @matthewjasper because this PR uses specialization. |
Prior to this change, cloning an Option value would branch on whether the Option was Some, even if it would be cheaper to just memcpy the bits. Default the current implementation, and then specialize it for Copy types, to avoid the branch.
Range<T> is not Copy even if T is Copy, which pessimizes the implementation of Option<Range>::clone. Specialize Option::clone for Range so that it can be more efficient. The specialization uses ptr::read to emulate Copy.
f412124
to
09c40e5
Compare
Usually we want specialization to go through a private trait, so the ability to specialize is not part of the public API. |
The thing that gets me here is that this also applies to every iterator -- a slice -- A quick godbolt to show current codegen: https://rust.godbolt.org/z/YnG7rK Brainstorming:
|
@ridiculousfish nice to see you trying out rust. Off-topic, we rewrote fish-update-completions in rust and it is almost done (logging and testing left).
@ridiculousfish Try checking out the recent vec extend iter changes for specialization, this change may need to do something similar. |
@ridiculousfish any updates on this? |
Sorry, this presumably needs more work than I can take on at the moment. Closing so it's not in th eway. |
These two commits improve the codegen of Option::clone.
The first commit "specializes"
Option<T: Copy>::clone
to a memcpy. For example, prior to this PR, cloning anOption<[u8; 8]>)
branches on the Option's discriminant (link). Copying the bytes without a branch is more efficient.The second commit adds the same optimization but specialized for
ops::Range
.Range<T: Copy>
is famously notCopy
(see #27186 and related); I do not intend to necro that discussion but I would like to see a more efficientclone()
. Because Range is not Copy, this version uses unsafeptr::read
to achieve the same effect.Note: the first commit has a user-visible behavior change in that
Option<T>::clone()
will no longer invokeT::clone()
if T is Copy. This was considered as OK in RFC 1521 but it might be worth calling out in release notes that it now affects Option.