Skip to content

Commit 84e9ee8

Browse files
Change implementation for entry()
Profiling showed that this function is quite the hotspot. By changing the implementation slightly, instead of walking the tree using the Linked List, but iterate directly over the values, we improve the throughput of certain CPU bound queries. We've seen a reduction in time needed of > 50% for certain rollup queries.
1 parent 1ef9858 commit 84e9ee8

File tree

1 file changed

+28
-15
lines changed

1 file changed

+28
-15
lines changed

crates/udd-sketch/src/lib.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,26 +134,39 @@ impl SketchHashMap {
134134
}
135135
}
136136

137+
/// Splits an entry if `key` is supposed to come right after it
138+
/// Returns the key *after* the one that was split.
139+
#[inline]
140+
fn entry_split(&mut self, key: SketchHashKey) -> SketchHashKey {
141+
for (k, e) in self.map.iter_mut() {
142+
if *k < key && e.next > key {
143+
let next = e.next;
144+
e.next = key;
145+
return next;
146+
}
147+
}
148+
unreachable!("Invalid key found");
149+
}
150+
137151
// Returns the entry for a given key.
138152
// If the entry doesn't yet exist, this function will create it
139153
// with 0 count and ensure the list of keys is correctly updated.
140154
fn entry(&mut self, key: SketchHashKey) -> &mut SketchHashEntry {
141-
let mut next = self.head;
142-
if !self.map.contains_key(&key) {
143-
if key < self.head {
144-
self.head = key;
145-
} else {
146-
let mut prev = SketchHashKey::Invalid;
147-
while key > next {
148-
prev = next;
149-
next = self.map[&next].next;
150-
}
151-
self.map.get_mut(&prev).expect("Invalid key found").next = key;
152-
}
155+
let mut new_entry = SketchHashEntry {
156+
count: 0,
157+
next: self.head,
158+
};
159+
160+
if key < self.head {
161+
self.head = key;
162+
} else if !self.map.contains_key(&key) {
163+
// Unfortunately, we'll now have to walk the whole map in order
164+
// to find the location where we should be inserted
165+
// into the single-linked list
166+
new_entry.next = self.entry_split(key);
153167
}
154-
self.map
155-
.entry(key)
156-
.or_insert(SketchHashEntry { count: 0, next })
168+
169+
self.map.entry(key).or_insert(new_entry)
157170
}
158171

159172
fn len(&self) -> usize {

0 commit comments

Comments
 (0)