Skip to content

Commit f13ccef

Browse files
committed
Auto merge of rust-lang#108448 - ishitatsuyuki:binary-heap, r=Mark-Simulacrum
binary_heap: Optimize Extend implementation. This PR makes the `Extend` implementation for `BinaryHeap` no longer rely on specialization, so that it always use the bulk rebuild optimization that was previously only available for the `Vec` specialization.
2 parents 932c173 + 116bb4d commit f13ccef

File tree

1 file changed

+19
-51
lines changed
  • library/alloc/src/collections/binary_heap

1 file changed

+19
-51
lines changed

library/alloc/src/collections/binary_heap/mod.rs

+19-51
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ use crate::collections::TryReserveError;
154154
use crate::slice;
155155
use crate::vec::{self, AsVecIntoIter, Vec};
156156

157-
use super::SpecExtend;
158-
159157
#[cfg(test)]
160158
mod tests;
161159

@@ -400,6 +398,17 @@ impl<T: fmt::Debug> fmt::Debug for BinaryHeap<T> {
400398
}
401399
}
402400

401+
struct RebuildOnDrop<'a, T: Ord> {
402+
heap: &'a mut BinaryHeap<T>,
403+
rebuild_from: usize,
404+
}
405+
406+
impl<'a, T: Ord> Drop for RebuildOnDrop<'a, T> {
407+
fn drop(&mut self) {
408+
self.heap.rebuild_tail(self.rebuild_from);
409+
}
410+
}
411+
403412
impl<T: Ord> BinaryHeap<T> {
404413
/// Creates an empty `BinaryHeap` as a max-heap.
405414
///
@@ -850,30 +859,19 @@ impl<T: Ord> BinaryHeap<T> {
850859
where
851860
F: FnMut(&T) -> bool,
852861
{
853-
struct RebuildOnDrop<'a, T: Ord> {
854-
heap: &'a mut BinaryHeap<T>,
855-
first_removed: usize,
856-
}
857-
858-
let mut guard = RebuildOnDrop { first_removed: self.len(), heap: self };
859-
862+
// rebuild_start will be updated to the first touched element below, and the rebuild will
863+
// only be done for the tail.
864+
let mut guard = RebuildOnDrop { rebuild_from: self.len(), heap: self };
860865
let mut i = 0;
866+
861867
guard.heap.data.retain(|e| {
862868
let keep = f(e);
863-
if !keep && i < guard.first_removed {
864-
guard.first_removed = i;
869+
if !keep && i < guard.rebuild_from {
870+
guard.rebuild_from = i;
865871
}
866872
i += 1;
867873
keep
868874
});
869-
870-
impl<'a, T: Ord> Drop for RebuildOnDrop<'a, T> {
871-
fn drop(&mut self) {
872-
// data[..first_removed] is untouched, so we only need to
873-
// rebuild the tail:
874-
self.heap.rebuild_tail(self.first_removed);
875-
}
876-
}
877875
}
878876
}
879877

@@ -1728,7 +1726,8 @@ impl<'a, T> IntoIterator for &'a BinaryHeap<T> {
17281726
impl<T: Ord> Extend<T> for BinaryHeap<T> {
17291727
#[inline]
17301728
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1731-
<Self as SpecExtend<I>>::spec_extend(self, iter);
1729+
let guard = RebuildOnDrop { rebuild_from: self.len(), heap: self };
1730+
guard.heap.data.extend(iter);
17321731
}
17331732

17341733
#[inline]
@@ -1742,37 +1741,6 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> {
17421741
}
17431742
}
17441743

1745-
impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> {
1746-
default fn spec_extend(&mut self, iter: I) {
1747-
self.extend_desugared(iter.into_iter());
1748-
}
1749-
}
1750-
1751-
impl<T: Ord> SpecExtend<Vec<T>> for BinaryHeap<T> {
1752-
fn spec_extend(&mut self, ref mut other: Vec<T>) {
1753-
let start = self.data.len();
1754-
self.data.append(other);
1755-
self.rebuild_tail(start);
1756-
}
1757-
}
1758-
1759-
impl<T: Ord> SpecExtend<BinaryHeap<T>> for BinaryHeap<T> {
1760-
fn spec_extend(&mut self, ref mut other: BinaryHeap<T>) {
1761-
self.append(other);
1762-
}
1763-
}
1764-
1765-
impl<T: Ord> BinaryHeap<T> {
1766-
fn extend_desugared<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1767-
let iterator = iter.into_iter();
1768-
let (lower, _) = iterator.size_hint();
1769-
1770-
self.reserve(lower);
1771-
1772-
iterator.for_each(move |elem| self.push(elem));
1773-
}
1774-
}
1775-
17761744
#[stable(feature = "extend_ref", since = "1.2.0")]
17771745
impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
17781746
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {

0 commit comments

Comments
 (0)