diff options
| author | Stjepan Glavina <stjepang@gmail.com> | 2017-02-08 12:19:50 +0100 |
|---|---|---|
| committer | Stjepan Glavina <stjepang@gmail.com> | 2017-02-08 12:19:50 +0100 |
| commit | 3bd6e46687b0d7ea347b6bb860bb1c35dfe2e7cc (patch) | |
| tree | 791dad2f3630c043267ec212cfb694a5a486456f | |
| parent | 4711ac314c3380f992e218879b7c94b26ba4102b (diff) | |
| download | rust-3bd6e46687b0d7ea347b6bb860bb1c35dfe2e7cc.tar.gz rust-3bd6e46687b0d7ea347b6bb860bb1c35dfe2e7cc.zip | |
Specialize `PartialOrd<A> for [A] where A: Ord`
This way we can call `cmp` instead of `partial_cmp` in the loop,
removing some burden of optimizing `Option`s away from the compiler.
PR #39538 introduced a regression where sorting slices suddenly became
slower, since `slice1.lt(slice2)` was much slower than
`slice1.cmp(slice2) == Less`. This problem is now fixed.
To verify, I benchmarked this simple program:
```rust
fn main() {
let mut v = (0..2_000_000).map(|x| x * x * x * 18913515181).map(|x| vec![x, x ^ 3137831591]).collect::<Vec<_>>();
v.sort();
}
```
Before this PR, it would take 0.95 sec, and now it takes 0.58 sec.
I also tried changing the `is_less` lambda to use `cmp` and
`partial_cmp`. Now all three versions (`lt`, `cmp`, `partial_cmp`) are
equally performant for sorting slices - all of them take 0.58 sec on the
benchmark.
| -rw-r--r-- | src/libcore/slice.rs | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 1a482b75731..18244cec7c7 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -2290,6 +2290,28 @@ impl<A> SlicePartialOrd<A> for [A] } } +impl<A> SlicePartialOrd<A> for [A] + where A: Ord +{ + default fn partial_compare(&self, other: &[A]) -> Option<Ordering> { + let l = cmp::min(self.len(), other.len()); + + // Slice to the loop iteration range to enable bound check + // elimination in the compiler + let lhs = &self[..l]; + let rhs = &other[..l]; + + for i in 0..l { + match lhs[i].cmp(&rhs[i]) { + Ordering::Equal => (), + non_eq => return Some(non_eq), + } + } + + self.len().partial_cmp(&other.len()) + } +} + impl SlicePartialOrd<u8> for [u8] { #[inline] fn partial_compare(&self, other: &[u8]) -> Option<Ordering> { |
