Skip to content

Specialize arena alloc for cloned slices #81053

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

Closed
wants to merge 1 commit into from

Conversation

bugadani
Copy link
Contributor

Copy contents of a slice.iter().cloned() directly into the arena. Also replace implementation of write_from_iter to something that can maybe be optimized better: https://rust.godbolt.org/z/qox784

Let me know if I did something entirely terribly incorrect with the custom Clonable specialization marker, I'm not sure if it's valid to add stuff like that.

@rust-highfive
Copy link
Contributor

r? @varkor

(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 Jan 15, 2021
@jyn514 jyn514 added I-compiletime Issue: Problems and improvements with respect to compile times. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 15, 2021
@jyn514
Copy link
Member

jyn514 commented Jan 15, 2021

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@bors
Copy link
Collaborator

bors commented Jan 15, 2021

⌛ Trying commit 9ab93f2 with merge 691e8249eca167a156669b07665b8be442f00e7c...

@@ -133,6 +160,10 @@ where
}
}

#[rustc_unsafe_specialization_marker]
trait Clonable: Clone {}
impl<T: Clone> Clonable for T {}
Copy link
Member

@the8472 the8472 Jan 15, 2021

Choose a reason for hiding this comment

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

My somewhat limited understanding of the min_specialization rules is that you're here promising that any specialization relying on Clonable will only be applied to types where T: Clone is not dependent lifetimes (directly or indirectly)
E.g. that there's no impl Clone for &'static Foo involved. That can only be guaranteed if you could also manually enumerate all T, i.e. they're not types supplied by external crates.

It would also mean that it's unsafe to use TypedArena for such types and users of it would have to uphold that in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not quite sure if this is the case, but I don't know the feature well enough. I was going by the example of FusedIterator and TrustedLen, both of which are implemented for e.g. std::slice::Iterator<'a, T: 'a> and I believe both are specialization marker traits.

Copy link
Member

Choose a reason for hiding this comment

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

The thing is that FusedIterator or TrustedLen are not implemented for arbitrary T. They're only implemented for structs controlled by std and those impl are only conditional on additional bounds that themselves are other specialization traits.

What's different here is that you're essentially declaring that any and all Clone types can act as a specialization marker for specializations relying on Clonable. This would only be valid when you have some way of reasoning about the set of T. And since T is what goes into TypedArena it means you've ensured that all uses of TypedArena are compatible with the min specialization rules. This kind of far-reaching obligation is why there's the word unsafe in that annotation.

But again, my understanding of min_specialization is quite limited, so I may be wrong here.

Copy link
Contributor Author

@bugadani bugadani Jan 15, 2021

Choose a reason for hiding this comment

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

All right, makes sense. I wish I had another way to specialize for Cloned<slice::Iter> :( Whatever else I tried, I got a conflicting implementation error....

But even then, perf may get back completely negative or neutral as well.

@bors
Copy link
Collaborator

bors commented Jan 15, 2021

☀️ Try build successful - checks-actions
Build commit: 691e8249eca167a156669b07665b8be442f00e7c (691e8249eca167a156669b07665b8be442f00e7c)

@rust-timer
Copy link
Collaborator

Queued 691e8249eca167a156669b07665b8be442f00e7c with parent bc39d4d, future comparison URL.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 15, 2021
let start_ptr = arena.alloc_raw_slice(len);
write_from_iter(self, len, start_ptr)
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't seem to rely on anything specific to Cloned. It just relies on the length. Wouldn't specializing on TrustedLen be sufficient here, considering that's already a specialization trait?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it wouldn't compile unfortunately, or at least I couldn't get it to. Cloned needs Clone on T.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, just specializing on anything TrustedLen is unsound, see #77945 for that. In short, Map is TrustedLen and can allocate on the same arena, which makes handling a panic safely an impossible nightmare of dropping uninitialized memory.

I went through the uses of alloc_from_iter and I found that most of those are Map and FlatMap, but some places allocate from Clonedslice::Iter so hence the PR.

Copy link
Member

Choose a reason for hiding this comment

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

I meant impl<I: TrustedLen> IterExt for I. That'll give you the length.

Copy link
Member

Choose a reason for hiding this comment

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

Well it's closed already. But for the record, you might have been able to use use impl<I: TrustedLen + IsClonedSliceIterMarker> for I instead where the latter bound is a safe specialization marker.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, this seems to compile:

#[rustc_specialization_trait]
trait IsClonedSliceIterMarker {}
impl<T> IsClonedSliceIterMarker for Cloned<Iter<'_, T>> {}

impl<T, I> IterExt<T> for I
where
    I: IntoIterator<Item = T> + IsClonedSliceIterMarker + TrustedLen,
{
    #[inline]
    fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
        let iter = self.into_iter();
        let len = iter.size_hint().0;
        if len == 0 {
            return &mut [];
        }
        // Move the content to the arena by copying and then forgetting it
        unsafe {
            let start_ptr = arena.alloc_raw_slice(len);
            write_from_iter(iter, len, start_ptr)
        }
    }
}

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit (691e8249eca167a156669b07665b8be442f00e7c): comparison url.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying rollup- to bors.

Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 16, 2021
@jyn514
Copy link
Member

jyn514 commented Jan 16, 2021

Looks like noise. Given the specialization is in question, I think it makes sense to close this.

@bugadani bugadani closed this Jan 16, 2021
@bugadani bugadani deleted the clone-slice-arena branch January 16, 2021 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-compiletime Issue: Problems and improvements with respect to compile times. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants