Skip to content

Commit 431da8c

Browse files
specialize the (common) k=2 case
1 parent 61ef0d7 commit 431da8c

1 file changed

Lines changed: 65 additions & 10 deletions

File tree

storage/src/qmdb/any/batch.rs

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -314,36 +314,91 @@ impl<'a, K: Ord, F: Family, V> DiffMerge<'a, K, F, V> {
314314
cursors: streams.into_iter().map(|s| (s, 0)).collect(),
315315
}
316316
}
317+
318+
fn peek_key(cursor: &(&'a DiffSlice<K, F, V>, usize)) -> Option<&'a K> {
319+
cursor.0.get(cursor.1).map(|(k, _)| k)
320+
}
317321
}
318322

319323
impl<'a, K: Ord, F: Family, V> Iterator for DiffMerge<'a, K, F, V> {
320324
type Item = (&'a K, &'a DiffEntry<F, V>);
321325

322326
fn next(&mut self) -> Option<Self::Item> {
327+
match self.cursors.len() {
328+
0 => None,
329+
1 => {
330+
let (slice, pos) = &mut self.cursors[0];
331+
let (k, entry) = slice.get(*pos)?;
332+
*pos += 1;
333+
Some((k, entry))
334+
}
335+
2 => {
336+
let ka = Self::peek_key(&self.cursors[0]);
337+
let kb = Self::peek_key(&self.cursors[1]);
338+
match (ka, kb) {
339+
(Some(a), Some(b)) => match a.cmp(b) {
340+
core::cmp::Ordering::Less => {
341+
let (slice, pos) = &mut self.cursors[0];
342+
let item = &slice[*pos];
343+
*pos += 1;
344+
Some((&item.0, &item.1))
345+
}
346+
core::cmp::Ordering::Greater => {
347+
let (slice, pos) = &mut self.cursors[1];
348+
let item = &slice[*pos];
349+
*pos += 1;
350+
Some((&item.0, &item.1))
351+
}
352+
core::cmp::Ordering::Equal => {
353+
let (slice, pos) = &mut self.cursors[0];
354+
let item = &slice[*pos];
355+
*pos += 1;
356+
self.cursors[1].1 += 1;
357+
Some((&item.0, &item.1))
358+
}
359+
},
360+
(Some(_), None) => {
361+
let (slice, pos) = &mut self.cursors[0];
362+
let item = &slice[*pos];
363+
*pos += 1;
364+
Some((&item.0, &item.1))
365+
}
366+
(None, Some(_)) => {
367+
let (slice, pos) = &mut self.cursors[1];
368+
let item = &slice[*pos];
369+
*pos += 1;
370+
Some((&item.0, &item.1))
371+
}
372+
(None, None) => None,
373+
}
374+
}
375+
_ => self.next_general(),
376+
}
377+
}
378+
}
379+
380+
impl<'a, K: Ord, F: Family, V> DiffMerge<'a, K, F, V> {
381+
fn next_general(&mut self) -> Option<(&'a K, &'a DiffEntry<F, V>)> {
323382
let n = self.cursors.len();
324383
let mut winner: Option<usize> = None;
325384
for level in 0..n {
326-
let (slice, pos) = self.cursors[level];
327-
let Some((k, _)) = slice.get(pos) else {
385+
let Some(k) = Self::peek_key(&self.cursors[level]) else {
328386
continue;
329387
};
330388
let better = match winner {
331389
None => true,
332-
Some(w) => {
333-
let (ws, wpos) = self.cursors[w];
334-
*k < ws[wpos].0
335-
}
390+
Some(w) => *k < *Self::peek_key(&self.cursors[w]).unwrap(),
336391
};
337392
if better {
338393
winner = Some(level);
339394
}
340395
}
341396
let level = winner?;
342397
let (slice, pos) = self.cursors[level];
343-
for inner in 0..n {
344-
let (s, p) = self.cursors[inner];
345-
if s.get(p).is_some_and(|(k, _)| *k == slice[pos].0) {
346-
self.cursors[inner].1 += 1;
398+
let winning_key = &slice[pos].0;
399+
for cursor in &mut self.cursors {
400+
if Self::peek_key(cursor).is_some_and(|k| k == winning_key) {
401+
cursor.1 += 1;
347402
}
348403
}
349404
Some((&slice[pos].0, &slice[pos].1))

0 commit comments

Comments
 (0)