rustdoc-search: use smart binary search in bitmaps

Addresses a comment from [jsha's benchmarking], where the `contains`
function showed up in the profiler. This commit pulls it from about
5% of the runtime to about 0.5%.

[jsha's benchmarking]: https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/search.20profiling/near/481868761
This commit is contained in:
Michael Howell 2024-11-18 11:34:53 -07:00
parent e83c45a98b
commit 3fbcc1f4b9

View file

@ -1053,9 +1053,17 @@ class RoaringBitmap {
contains(keyvalue) {
const key = keyvalue >> 16;
const value = keyvalue & 0xFFFF;
for (let i = 0; i < this.keys.length; ++i) {
if (this.keys[i] === key) {
return this.containers[i].contains(value);
let left = 0;
let right = this.keys.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
const x = this.keys[mid];
if (x < key) {
left = mid + 1;
} else if (x > key) {
right = mid - 1;
} else {
return this.containers[mid].contains(value);
}
}
return false;
@ -1068,11 +1076,18 @@ class RoaringBitmapRun {
this.array = array;
}
contains(value) {
const l = this.runcount * 4;
for (let i = 0; i < l; i += 4) {
let left = 0;
let right = this.runcount - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
const i = mid * 4;
const start = this.array[i] | (this.array[i + 1] << 8);
const lenm1 = this.array[i + 2] | (this.array[i + 3] << 8);
if (value >= start && value <= (start + lenm1)) {
if ((start + lenm1) < value) {
left = mid + 1;
} else if (start > value) {
right = mid - 1;
} else {
return true;
}
}
@ -1085,10 +1100,17 @@ class RoaringBitmapArray {
this.array = array;
}
contains(value) {
const l = this.cardinality * 2;
for (let i = 0; i < l; i += 2) {
const start = this.array[i] | (this.array[i + 1] << 8);
if (value === start) {
let left = 0;
let right = this.cardinality - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
const i = mid * 2;
const x = this.array[i] | (this.array[i + 1] << 8);
if (x < value) {
left = mid + 1;
} else if (x > value) {
right = mid - 1;
} else {
return true;
}
}