Skip to content

Commit 720845d

Browse files
authored
Avoid sift_down for unmutated PeekMut (rust#75974) (#27)
* Avoid sift_down for unmutated PeekMut (rust#75974) * Bump MSRV to 1.32.0
1 parent fc5e4c3 commit 720845d

File tree

6 files changed

+105
-4
lines changed

6 files changed

+105
-4
lines changed

.github/workflows/rust.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- macos-latest
1717
rust:
1818
- stable
19-
- 1.31.1 # MSRV (Rust 2018)
19+
- 1.32.0 # MSRV (Rust 2018 and rand support)
2020
cargo_args:
2121
- ""
2222
- --features serde

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Changed
10+
11+
* Bump MSRV (minimum supported rust version) to rust 1.32.0.
12+
913
## [0.3.1] - 2020-09-24
1014

1115
### Added
@@ -68,4 +72,4 @@ https://rust-lang-nursery.github.io/api-guidelines/interoperability.html#c-serde
6872

6973
## [0.1.1] - 2018-05-14
7074

71-
* Initial tag
75+
* Initial tag

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ serde = { version = "1.0.116", optional = true, features = ["derive"] }
1616

1717
[dev-dependencies]
1818
serde_json = "1.0.57"
19+
rand = "0.7.3"
1920

2021
[badges]
2122
# TODO: waiting for PR to land...: https://github.com/rust-lang/crates.io/pull/1838#

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Other notable added methods are:
2121

2222
## MSRV (Minimum Supported Rust Version)
2323

24-
This crate requires Rust 1.31.1 or later.
24+
This crate requires Rust 1.32.0 or later.
2525

2626
# Changes
2727

benches/binary_heap.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#![feature(test)]
2+
3+
extern crate test;
4+
5+
use binary_heap_plus::BinaryHeap;
6+
7+
use rand::{seq::SliceRandom, thread_rng};
8+
use test::{black_box, Bencher};
9+
10+
#[bench]
11+
fn bench_find_smallest_1000(b: &mut Bencher) {
12+
let mut rng = thread_rng();
13+
let mut vec: Vec<u32> = (0..100_000).collect();
14+
vec.shuffle(&mut rng);
15+
16+
b.iter(|| {
17+
let mut iter = vec.iter().copied();
18+
let mut heap: BinaryHeap<_> = iter.by_ref().take(1000).collect();
19+
20+
for x in iter {
21+
let mut max = heap.peek_mut().unwrap();
22+
// This comparison should be true only 1% of the time.
23+
// Unnecessary `sift_down`s will degrade performance
24+
if x < *max {
25+
*max = x;
26+
}
27+
}
28+
29+
heap
30+
})
31+
}
32+
33+
#[bench]
34+
fn bench_peek_mut_deref_mut(b: &mut Bencher) {
35+
let mut bheap = BinaryHeap::from(vec![42]);
36+
let vec: Vec<u32> = (0..1_000_000).collect();
37+
38+
b.iter(|| {
39+
let vec = black_box(&vec);
40+
let mut peek_mut = bheap.peek_mut().unwrap();
41+
// The compiler shouldn't be able to optimize away the `sift_down`
42+
// assignment in `PeekMut`'s `DerefMut` implementation since
43+
// the loop may not run.
44+
for &i in vec.iter() {
45+
*peek_mut = i;
46+
}
47+
// Remove the already minimal overhead of the sift_down
48+
std::mem::forget(peek_mut);
49+
})
50+
}
51+
52+
#[bench]
53+
fn bench_from_vec(b: &mut Bencher) {
54+
let mut rng = thread_rng();
55+
let mut vec: Vec<u32> = (0..100_000).collect();
56+
vec.shuffle(&mut rng);
57+
58+
b.iter(|| BinaryHeap::from(vec.clone()))
59+
}
60+
61+
#[bench]
62+
fn bench_into_sorted_vec(b: &mut Bencher) {
63+
let bheap: BinaryHeap<i32> = (0..10_000).collect();
64+
65+
b.iter(|| bheap.clone().into_sorted_vec())
66+
}
67+
68+
#[bench]
69+
fn bench_push(b: &mut Bencher) {
70+
let mut bheap = BinaryHeap::with_capacity(50_000);
71+
let mut rng = thread_rng();
72+
let mut vec: Vec<u32> = (0..50_000).collect();
73+
vec.shuffle(&mut rng);
74+
75+
b.iter(|| {
76+
for &i in vec.iter() {
77+
bheap.push(i);
78+
}
79+
black_box(&mut bheap);
80+
bheap.clear();
81+
})
82+
}
83+
84+
#[bench]
85+
fn bench_pop(b: &mut Bencher) {
86+
let mut bheap = BinaryHeap::with_capacity(10_000);
87+
88+
b.iter(|| {
89+
bheap.extend((0..10_000).rev());
90+
black_box(&mut bheap);
91+
while let Some(elem) = bheap.pop() {
92+
black_box(elem);
93+
}
94+
})
95+
}

src/binary_heap.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ impl<'a, T, C: Compare<T>> Deref for PeekMut<'a, T, C> {
335335
// #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
336336
impl<'a, T, C: Compare<T>> DerefMut for PeekMut<'a, T, C> {
337337
fn deref_mut(&mut self) -> &mut T {
338+
self.sift = true;
338339
&mut self.heap.data[0]
339340
}
340341
}
@@ -751,7 +752,7 @@ impl<T, C: Compare<T>> BinaryHeap<T, C> {
751752
} else {
752753
Some(PeekMut {
753754
heap: self,
754-
sift: true,
755+
sift: false,
755756
})
756757
}
757758
}

0 commit comments

Comments
 (0)