about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-02-11 04:37:27 +0000
committerbors <bors@rust-lang.org>2017-02-11 04:37:27 +0000
commitf140a6c6effa9fe11f97373d995e6c0d977b509f (patch)
tree4034fda15457a4b02094cd845786789081dc8b68
parent064a0ee131b3129fcad68570975ccc85d0fb54d0 (diff)
parenta344c126d03729a9d147f18dfc9cc6432bc790fd (diff)
downloadrust-f140a6c6effa9fe11f97373d995e6c0d977b509f.tar.gz
rust-f140a6c6effa9fe11f97373d995e6c0d977b509f.zip
Auto merge of #39642 - stjepang:specialize-slice-partialord, r=alexcrichton
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.

Tangentially, as soon as we get `default impl`, it might be a good idea to implement a blanket default impl for `lt`, `gt`, `le`, `ge` in terms of `cmp` whenever possible. Today, those four functions by default are only implemented in terms of `partial_cmp`.

r? @alexcrichton
-rw-r--r--src/libcore/slice.rs7
1 files changed, 4 insertions, 3 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 1a482b75731..3e0b8425573 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -2290,9 +2290,10 @@ impl<A> SlicePartialOrd<A> for [A]
     }
 }
 
-impl SlicePartialOrd<u8> for [u8] {
-    #[inline]
-    fn partial_compare(&self, other: &[u8]) -> Option<Ordering> {
+impl<A> SlicePartialOrd<A> for [A]
+    where A: Ord
+{
+    default fn partial_compare(&self, other: &[A]) -> Option<Ordering> {
         Some(SliceOrd::compare(self, other))
     }
 }