Skip to content

Commit 32c780b

Browse files
committed
perf: avoid re-searching the ART for the item we just inserted
1 parent 7d0e9be commit 32c780b

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

src/roaring64.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,6 +1948,11 @@ roaring64_bitmap_t *roaring64_bitmap_add_offset_signed(
19481948
return answer;
19491949
}
19501950

1951+
// Track the most recently inserted hi container so that the next
1952+
// iteration's lo can merge with it without re-searching the ART.
1953+
leaf_t *prev_hi_leaf = NULL;
1954+
int64_t prev_hi_k = -1;
1955+
19511956
while (it.value != NULL) {
19521957
leaf_t leaf = (leaf_t)*it.value;
19531958
int64_t k = (int64_t)(combine_key(it.key, 0) >> 16) + container_offset;
@@ -1972,31 +1977,33 @@ roaring64_bitmap_t *roaring64_bitmap_add_offset_signed(
19721977
container_add_offset(c, typecode, lo_ptr, hi_ptr, in_offset);
19731978

19741979
if (lo != NULL) {
1975-
uint8_t lo_high48[ART_KEY_BYTES];
1976-
split_key((uint64_t)k << 16, lo_high48);
1977-
leaf_t *existing_leaf = (leaf_t *)art_find(&answer->art, lo_high48);
1978-
if (existing_leaf != NULL) {
1979-
uint8_t existing_type = get_typecode(*existing_leaf);
1980-
container_t *existing_c = get_container(answer, *existing_leaf);
1980+
if (prev_hi_leaf != NULL && prev_hi_k == k) {
1981+
uint8_t existing_type = get_typecode(*prev_hi_leaf);
1982+
container_t *existing_c = get_container(answer, *prev_hi_leaf);
19811983
uint8_t merged_type;
19821984
container_t *merged_c = container_ior(
19831985
existing_c, existing_type, lo, typecode, &merged_type);
19841986
if (merged_c != existing_c) {
19851987
container_free(existing_c, existing_type);
19861988
}
1987-
replace_container(answer, existing_leaf, merged_c, merged_type);
1989+
replace_container(answer, prev_hi_leaf, merged_c, merged_type);
19881990
container_free(lo, typecode);
19891991
} else {
1992+
uint8_t lo_high48[ART_KEY_BYTES];
1993+
split_key((uint64_t)k << 16, lo_high48);
19901994
leaf_t new_leaf = add_container(answer, lo, typecode);
19911995
art_insert(&answer->art, lo_high48, (art_val_t)new_leaf);
19921996
}
19931997
}
19941998

1999+
prev_hi_leaf = NULL;
19952000
if (hi != NULL) {
19962001
uint8_t hi_high48[ART_KEY_BYTES];
19972002
split_key((uint64_t)(k + 1) << 16, hi_high48);
19982003
leaf_t new_leaf = add_container(answer, hi, typecode);
1999-
art_insert(&answer->art, hi_high48, (art_val_t)new_leaf);
2004+
prev_hi_leaf = (leaf_t *)art_insert(&answer->art, hi_high48,
2005+
(art_val_t)new_leaf);
2006+
prev_hi_k = k + 1;
20002007
}
20012008

20022009
art_iterator_next(&it);

0 commit comments

Comments
 (0)