Auto merge of #137704 - nnethercote:opt-empty-prov-range-checks, r=oli-obk
Optimize empty provenance range checks. Currently it gets the pointers in the range and checks if the result is empty, but it can be done faster if you combine those two steps. r? `@oli-obk`
This commit is contained in:
commit
daf59857d6
2 changed files with 60 additions and 10 deletions
|
@ -1,4 +1,5 @@
|
|||
use std::borrow::Borrow;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::Debug;
|
||||
use std::mem;
|
||||
use std::ops::{Bound, Index, IndexMut, RangeBounds};
|
||||
|
@ -156,6 +157,38 @@ impl<K: Ord, V> SortedMap<K, V> {
|
|||
&self.data[start..end]
|
||||
}
|
||||
|
||||
/// `sm.range_is_empty(r)` == `sm.range(r).is_empty()`, but is faster.
|
||||
#[inline]
|
||||
pub fn range_is_empty<R>(&self, range: R) -> bool
|
||||
where
|
||||
R: RangeBounds<K>,
|
||||
{
|
||||
// `range` must (via `range_slice_indices`) search for the start and
|
||||
// end separately. But here we can do a single binary search for the
|
||||
// entire range. If a single `x` matching `range` is found then the
|
||||
// range is *not* empty.
|
||||
self.data
|
||||
.binary_search_by(|(x, _)| {
|
||||
// Is `x` below `range`?
|
||||
match range.start_bound() {
|
||||
Bound::Included(start) if x < start => return Ordering::Less,
|
||||
Bound::Excluded(start) if x <= start => return Ordering::Less,
|
||||
_ => {}
|
||||
};
|
||||
|
||||
// Is `x` above `range`?
|
||||
match range.end_bound() {
|
||||
Bound::Included(end) if x > end => return Ordering::Greater,
|
||||
Bound::Excluded(end) if x >= end => return Ordering::Greater,
|
||||
_ => {}
|
||||
};
|
||||
|
||||
// `x` must be within `range`.
|
||||
Ordering::Equal
|
||||
})
|
||||
.is_err()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remove_range<R>(&mut self, range: R)
|
||||
where
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue