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

Optimize Option::clone to Copy when possible #76551

Closed
wants to merge 2 commits into from
Closed

Optimize Option::clone to Copy when possible #76551

wants to merge 2 commits into from

Conversation

ridiculousfish
Copy link
Contributor

This is a pair of commits that attempt to improve the codegen of
Option::clone.

The first commit "specializes" Option<T: Copy>::clone to a memcpy. For
example, as of this PR, cloning an Option<[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 Range.
Range<T: Copy> is famously not Copy (see #27186 and related); I do not
propose to necro that discussion but I would like to see a more efficient
clone(). Because Range is not Copy, this version uses unsafe ptr::read to
achieve the same effect.

Note: the first commit has a user-visible behavior change in that
Option::clone() will no longer invoke T::clone() if T is Copy. This was
considered as OK in RFC 1521
but it might be worth calling out in release notes.

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.
@rust-highfive
Copy link
Collaborator

r? @shepmaster

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 10, 2020
@ridiculousfish ridiculousfish deleted the fix-option-clone branch September 10, 2020 01:44
@ridiculousfish
Copy link
Contributor Author

Bad commits, will redo

@@ -1228,22 +1228,36 @@ fn expect_none_failed(msg: &str, value: &dyn fmt::Debug) -> ! {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for Option<T> {
#[inline]
fn clone(&self) -> Self {
default fn clone(&self) -> Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure you check how specialization is used for iterators. As I understand it, it's always behind a helper trait so that specialization doesn't leak out into the public API (like I think this would).

@shepmaster
Copy link
Member

It will be good to show benchmarks comparing the before/after performance to help justify the change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants