Skip to content

Commit c013dc0

Browse files
authored
Rollup merge of #81127 - hanmertens:binary_heap_sift_down_perf, r=dtolnay
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
2 parents 4b9f5cc + 095bf01 commit c013dc0

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

library/alloc/src/collections/binary_heap.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ impl<T: Ord> BinaryHeap<T> {
566566
let mut child = 2 * hole.pos() + 1;
567567

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

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

0 commit comments

Comments
 (0)