Skip to content

Commit

Permalink
Rollup merge of #81127 - hanmertens:binary_heap_sift_down_perf, r=dto…
Browse files Browse the repository at this point in the history
…lnay

Improve sift_down performance in BinaryHeap

Replacing `child < end - 1` with `child <= end.saturating_sub(2)` in `BinaryHeap::sift_down_range` (surprisingly) results in a significant speedup of `BinaryHeap::into_sorted_vec`. The same substitution can be done for `BinaryHeap::sift_down_to_bottom`, which causes a slight but probably statistically insignificant speedup for `BinaryHeap::pop`. It's interesting that benchmarks aside from `bench_into_sorted_vec` are barely affected, even those that do use `sift_down_*` methods internally.

| Benchmark                | Before (ns/iter) | After (ns/iter) | Speedup |
|--------------------------|------------------|-----------------|---------|
| bench_find_smallest_1000<sup>1</sup> | 392,617          | 385,200         |    1.02 |
| bench_from_vec<sup>1</sup>           | 506,016          | 504,444         |    1.00 |
| bench_into_sorted_vec<sup>1</sup>    | 476,869          | 384,458         |    1.24 |
| bench_peek_mut_deref_mut<sup>3</sup> | 518,753          | 519,792         |    1.00 |
| bench_pop<sup>2</sup>                | 446,718          | 444,409         |    1.01 |
| bench_push<sup>3</sup>               | 772,481          | 770,208         |    1.00 |

<sup>1</sup>: internally calls `sift_down_range`
<sup>2</sup>: internally calls `sift_down_to_bottom`
<sup>3</sup>: should not be affected
  • Loading branch information
m-ou-se committed Mar 9, 2021
2 parents 4b9f5cc + 095bf01 commit c013dc0
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions library/alloc/src/collections/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ impl<T: Ord> BinaryHeap<T> {
let mut child = 2 * hole.pos() + 1;

// Loop invariant: child == 2 * hole.pos() + 1.
while child < end - 1 {
while child <= end.saturating_sub(2) {
// compare with the greater of the two children
// SAFETY: child < end - 1 < self.len() and
// child + 1 < end <= self.len(), so they're valid indexes.
Expand Down Expand Up @@ -625,7 +625,7 @@ impl<T: Ord> BinaryHeap<T> {
let mut child = 2 * hole.pos() + 1;

// Loop invariant: child == 2 * hole.pos() + 1.
while child < end - 1 {
while child <= end.saturating_sub(2) {
// SAFETY: child < end - 1 < self.len() and
// child + 1 < end <= self.len(), so they're valid indexes.
// child == 2 * hole.pos() + 1 != hole.pos() and
Expand Down

0 comments on commit c013dc0

Please sign in to comment.