Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upImplement feature sort_unstable #40601
Conversation
rust-highfive
assigned
alexcrichton
Mar 17, 2017
stjepang
reviewed
Mar 17, 2017
| /// ``` | ||
| #[stable(feature = "rust1", since = "1.0.0")] | ||
| #[inline] | ||
| pub fn sort_by<F>(&mut self, mut compare: F) |
This comment has been minimized.
This comment has been minimized.
stjepang
Mar 17, 2017
Author
Contributor
This function is not added or anything. It was just reordered with sort_by_key.
Previous order: sort, sort_by_key, sort_by.
Current order: sort, sort_by, sort_by_key.
stjepang
reviewed
Mar 17, 2017
| /// ``` | ||
| /// | ||
| /// [pdqsort]: https://github.com/orlp/pdqsort | ||
| // FIXME #40585: Mention `sort_unstable` in the documentation for `sort`. |
This comment has been minimized.
This comment has been minimized.
stjepang
Mar 17, 2017
Author
Contributor
FIXME because we shouldn't mention unstable functions in the documentation for stable functions.... right?
I assume we'll fix this as soon as the feature gets stabilized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Mar 17, 2017
Member
Yeah that seems reasonable to me, punting on this for now until the function is stabilized.
stjepang
reviewed
Mar 17, 2017
| // to perform better than merge sort. For bigger types `T`, the threshold is smaller. | ||
| // | ||
| // Short runs are extended using insertion sort to span at least `min_run` elements, in order | ||
| // to improve performance. |
This comment has been minimized.
This comment has been minimized.
stjepang
Mar 17, 2017
Author
Contributor
I don't believe it's worthwhile differentiating between big and small Ts - it doesn't have a large effect.
Instead, it's better to focus on some middle ground that works well all around: big/small Ts and expensive/cheap comparison functions as well. I took a look at a std::stable_sort implementation in C++ and it has similar constants.
This comment has been minimized.
This comment has been minimized.
|
|
stjepang
force-pushed the
stjepang:sort-unstable
branch
from
f421527
to
50eb24b
Mar 17, 2017
This comment has been minimized.
This comment has been minimized.
|
I have troubles making Travis tests pass - the problem is in The compiler warns about unused future, and warnings are configured to be denied. Whatever I do, the compiler complains one way or another... Any idea how to fix that? :/ |
alexcrichton
reviewed
Mar 17, 2017
|
Awesome implementation, thanks for the PR! I didn't review the sorting itself in too close detail, but everything I looked at seemed quite solid. |
| @@ -52,6 +52,7 @@ | |||
| #![feature(shared)] | |||
| #![feature(slice_get_slice)] | |||
| #![feature(slice_patterns)] | |||
| #![feature(sort_unstable)] | |||
This comment has been minimized.
This comment has been minimized.
alexcrichton
Mar 17, 2017
Member
I think Travis is failing on this line during tests: https://travis-ci.org/rust-lang/rust/jobs/212204751
| /// ``` | ||
| /// | ||
| /// [pdqsort]: https://github.com/orlp/pdqsort | ||
| // FIXME #40585: Mention `sort_unstable` in the documentation for `sort`. |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Mar 17, 2017
Member
Yeah that seems reasonable to me, punting on this for now until the function is stabilized.
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// let mut v = [-5, 4, 1, -3, 2]; |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Mar 17, 2017
Member
I think you'll need to add #![feature] to this doctest to get past bors
This comment has been minimized.
This comment has been minimized.
| //! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our | ||
| //! stable sorting implementation. | ||
|
|
||
| #![unstable(feature = "sort_unstable", issue = "40585")] |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Mar 17, 2017
Member
It should be ok to omit this annotation I believe as it's a private module anyway.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Oh your fix for |
alexcrichton
referenced this pull request
Mar 17, 2017
Merged
Implement a faster sort algorithm #38192
This comment has been minimized.
This comment has been minimized.
|
Not long ago we discussed what guarantees |
stjepang
referenced this pull request
Mar 17, 2017
Merged
Add docs for sort_unstable to unstable book #40619
This comment has been minimized.
This comment has been minimized.
|
I managed to close the gap between stable and unstable sorting on ascending & descending inputs (see the new benchmarks). :) One more thing: pdqsort falls back to heapsort after several imbalanced partitions. I'm pretty sure we never hit this case in our tests, so it'd be wise to write tests for heapsort ( |
stjepang
force-pushed the
stjepang:sort-unstable
branch
4 times, most recently
from
6764eb0
to
7322ce8
Mar 18, 2017
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@stjepang Perhaps you can trigger the worst case using a modification of the technique described in the 1999 paper "A Killer Adversary for Quicksort" by M. D. McIlroy. I used it a couple years ago to prove that libc++'s sort routine is quadratic. |
This comment has been minimized.
This comment has been minimized.
|
Also, for those interested in a deeper explanation in the how/why of pattern-defeating quicksort, a (nearly finished) draft of my paper is available here: https://drive.google.com/file/d/0B1-vl-dPgKm_T0Fxeno1a0lGT0E/view There are some subtle differences between my C++ implementation and @stjepang's version due to design goals, so some parts might not apply, but most of it does. |
stjepang
force-pushed the
stjepang:sort-unstable
branch
4 times, most recently
from
b22c8ca
to
36bc0f4
Mar 19, 2017
This comment has been minimized.
This comment has been minimized.
|
@stjepang I guess the new pub(...) syntax doesn't help here since code/test is in different crates? |
This comment has been minimized.
This comment has been minimized.
|
@arthurprs No, doesn't help unfortunately. They are totally separate crates. However, I did a workaround @alexcrichton suggested to me over IRC - expose the heapsort function publicly, but gate it through a dummy feature. Can't say I feel good about this hack, but apparently there's no better option at the moment. |
stjepang
force-pushed the
stjepang:sort-unstable
branch
from
c86c8ee
to
038d605
Mar 21, 2017
This comment has been minimized.
This comment has been minimized.
|
@bors: r+ Yeah perhaps one day we'll be able to move tests back into core (maybe selectively this time) but for now this is functionally the same (an internal function to the library) |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
|
stjepang
added some commits
Mar 17, 2017
stjepang
force-pushed the
stjepang:sort-unstable
branch
from
038d605
to
a718051
Mar 21, 2017
This comment has been minimized.
This comment has been minimized.
|
@bors: r+ |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
|
bors
added a commit
that referenced
this pull request
Mar 21, 2017
This comment has been minimized.
This comment has been minimized.
|
|
stjepang commentedMar 17, 2017
•
edited
Tracking issue for the feature: #40585
This is essentially integration of pdqsort into libcore.
There's plenty of unsafe blocks to review. The heart of pdqsort is
fn partition_in_blocksand is probably the most challenging function to understand. It requires some patience, but let me know if you find it too difficult - comments could always be improved.Changes
sort_unstablefeature.sort_large_big_randomis 35% faster). The old constants were highly optimized for sorting integers, so overall the configuration is more balanced now. A minor regression in case of integers is forgivable as we recently had performance improvements (#39538) that completely make up for it.Benchmarks
The following table compares stable and unstable sorting:
Interesting cases:
large_descending- unstable sort is slightly faster. Both just check whether the slice is descending and if so, they reverse it. I believe the slight difference in performance is because unstable sort traces the slice forwards, while stable sort goes backwards.r? @alexcrichton