Skip to content

Commit 5831421

Browse files
author
Markus Westerlind
committed
perf: Remove the need for unwrap when using ProbeSeq
1 parent 297917d commit 5831421

File tree

1 file changed

+14
-25
lines changed

1 file changed

+14
-25
lines changed

src/raw/mod.rs

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -145,27 +145,21 @@ fn h2(hash: u64) -> u8 {
145145
/// Proof that the probe will visit every group in the table:
146146
/// <https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/>
147147
struct ProbeSeq {
148-
bucket_mask: usize,
149148
pos: usize,
150149
stride: usize,
151150
}
152151

153-
impl Iterator for ProbeSeq {
154-
type Item = usize;
155-
156-
#[inline]
157-
fn next(&mut self) -> Option<usize> {
152+
impl ProbeSeq {
153+
fn move_next(&mut self, bucket_mask: usize) {
158154
// We should have found an empty bucket by now and ended the probe.
159155
debug_assert!(
160-
self.stride <= self.bucket_mask,
156+
self.stride <= bucket_mask,
161157
"Went past end of probe sequence"
162158
);
163159

164-
let result = self.pos;
165160
self.stride += Group::WIDTH;
166161
self.pos += self.stride;
167-
self.pos &= self.bucket_mask;
168-
Some(result)
162+
self.pos &= bucket_mask;
169163
}
170164
}
171165

@@ -578,15 +572,14 @@ impl<T> RawTable<T> {
578572
}
579573
}
580574

581-
/// Returns an iterator for a probe sequence on the table.
575+
/// Returns an iterator-like object for a probe sequence on the table.
582576
///
583577
/// This iterator never terminates, but is guaranteed to visit each bucket
584578
/// group exactly once. The loop using `probe_seq` must terminate upon
585579
/// reaching a group containing an empty bucket.
586580
#[cfg_attr(feature = "inline-more", inline)]
587581
fn probe_seq(&self, hash: u64) -> ProbeSeq {
588582
ProbeSeq {
589-
bucket_mask: self.bucket_mask,
590583
pos: h1(hash) & self.bucket_mask,
591584
stride: 0,
592585
}
@@ -626,7 +619,9 @@ impl<T> RawTable<T> {
626619
/// There must be at least 1 empty bucket in the table.
627620
#[cfg_attr(feature = "inline-more", inline)]
628621
fn find_insert_slot(&self, hash: u64) -> usize {
629-
for pos in self.probe_seq(hash) {
622+
let mut probe_seq = self.probe_seq(hash);
623+
loop {
624+
let pos = probe_seq.pos;
630625
unsafe {
631626
let group = Group::load(self.ctrl(pos));
632627
if let Some(bit) = group.match_empty_or_deleted().lowest_set_bit() {
@@ -652,10 +647,8 @@ impl<T> RawTable<T> {
652647
}
653648
}
654649
}
650+
probe_seq.move_next(self.bucket_mask);
655651
}
656-
657-
// probe_seq never returns.
658-
unreachable!();
659652
}
660653

661654
/// Marks all table buckets as empty without dropping their contents.
@@ -1872,8 +1865,6 @@ pub struct RawIterHash<'a, T> {
18721865
// The sequence of groups to probe in the search.
18731866
probe_seq: ProbeSeq,
18741867

1875-
// The current group and its position.
1876-
pos: usize,
18771868
group: Group,
18781869

18791870
// The elements within the group with a matching h2-hash.
@@ -1884,16 +1875,14 @@ impl<'a, T> RawIterHash<'a, T> {
18841875
fn new(table: &'a RawTable<T>, hash: u64) -> Self {
18851876
unsafe {
18861877
let h2_hash = h2(hash);
1887-
let mut probe_seq = table.probe_seq(hash);
1888-
let pos = probe_seq.next().unwrap();
1889-
let group = Group::load(table.ctrl(pos));
1878+
let probe_seq = table.probe_seq(hash);
1879+
let group = Group::load(table.ctrl(probe_seq.pos));
18901880
let bitmask = group.match_byte(h2_hash).into_iter();
18911881

18921882
RawIterHash {
18931883
table,
18941884
h2_hash,
18951885
probe_seq,
1896-
pos,
18971886
group,
18981887
bitmask,
18991888
}
@@ -1908,15 +1897,15 @@ impl<'a, T> Iterator for RawIterHash<'a, T> {
19081897
unsafe {
19091898
loop {
19101899
if let Some(bit) = self.bitmask.next() {
1911-
let index = (self.pos + bit) & self.table.bucket_mask;
1900+
let index = (self.probe_seq.pos + bit) & self.table.bucket_mask;
19121901
let bucket = self.table.bucket(index);
19131902
return Some(bucket);
19141903
}
19151904
if likely(self.group.match_empty().any_bit_set()) {
19161905
return None;
19171906
}
1918-
self.pos = self.probe_seq.next().unwrap();
1919-
self.group = Group::load(self.table.ctrl(self.pos));
1907+
self.probe_seq.move_next(self.table.bucket_mask);
1908+
self.group = Group::load(self.table.ctrl(self.probe_seq.pos));
19201909
self.bitmask = self.group.match_byte(self.h2_hash).into_iter();
19211910
}
19221911
}

0 commit comments

Comments
 (0)