about summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2021-03-09 09:05:18 +0000
committerGitHub <noreply@github.com>2021-03-09 09:05:18 +0000
commitc013dc01f1babb8f8e0dddcfdc69a84e8249161a (patch)
treea74dc5634cb8fb4d3f5c7048374cab88fa9659c7 /library/alloc/src
parent4b9f5cc4c10a161047475cb9bbe02c4fda57fb07 (diff)
parent095bf01649a202b088c817bcdd3612d2604187e0 (diff)
downloadrust-c013dc01f1babb8f8e0dddcfdc69a84e8249161a.tar.gz
rust-c013dc01f1babb8f8e0dddcfdc69a84e8249161a.zip
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
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/collections/binary_heap.rs4
1 files changed, 2 insertions, 2 deletions
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index 4377780e15f..b5e66d37ab4 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -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.
@@ -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