Skip to content

Commit 1b208b1

Browse files
authored
Rollup merge of rust-lang#67948 - llogiq:gallop, r=Mark-Simulacrum
Galloping search for binary_search_util This is unlikely to improve perf much unless for synthetic benchmarks, but I figure it likely won't hurt either.
2 parents 1d9c69f + 0e1cd59 commit 1b208b1

File tree

1 file changed

+40
-20
lines changed
  • src/librustc_data_structures/binary_search_util

1 file changed

+40
-20
lines changed

src/librustc_data_structures/binary_search_util/mod.rs

+40-20
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,55 @@ where
1414
Ok(mid) => mid,
1515
Err(_) => return &[],
1616
};
17+
let size = data.len();
1718

18-
// We get back *some* element with the given key -- so
19-
// search backwards to find the *first* one.
20-
//
21-
// (It'd be more efficient to use a "galloping" search
22-
// here, but it's not really worth it for small-ish
23-
// amounts of data.)
19+
// We get back *some* element with the given key -- so do
20+
// a galloping search backwards to find the *first* one.
2421
let mut start = mid;
25-
while start > 0 {
26-
if key_fn(&data[start - 1]) == *key {
27-
start -= 1;
28-
} else {
22+
let mut previous = mid;
23+
let mut step = 1;
24+
loop {
25+
start = start.saturating_sub(step);
26+
if start == 0 || key_fn(&data[start]) != *key {
2927
break;
3028
}
29+
previous = start;
30+
step *= 2;
31+
}
32+
step = previous - start;
33+
while step > 1 {
34+
let half = step / 2;
35+
let mid = start + half;
36+
if key_fn(&data[mid]) != *key {
37+
start = mid;
38+
}
39+
step -= half;
40+
}
41+
// adjust by one if we have overshot
42+
if start < size && key_fn(&data[start]) != *key {
43+
start += 1;
3144
}
3245

3346
// Now search forward to find the *last* one.
34-
//
35-
// (It'd be more efficient to use a "galloping" search
36-
// here, but it's not really worth it for small-ish
37-
// amounts of data.)
38-
let mut end = mid + 1;
39-
let max = data.len();
40-
while end < max {
41-
if key_fn(&data[end]) == *key {
42-
end += 1;
43-
} else {
47+
let mut end = mid;
48+
let mut previous = mid;
49+
let mut step = 1;
50+
loop {
51+
end = end.saturating_add(step).min(size);
52+
if end == size || key_fn(&data[end]) != *key {
4453
break;
4554
}
55+
previous = end;
56+
step *= 2;
57+
}
58+
step = end - previous;
59+
while step > 1 {
60+
let half = step / 2;
61+
let mid = end - half;
62+
if key_fn(&data[mid]) != *key {
63+
end = mid;
64+
}
65+
step -= half;
4666
}
4767

4868
&data[start..end]

0 commit comments

Comments
 (0)