Skip to content

Use binary search in ArrayRangeSet#2614

Open
fabalchemy wants to merge 1 commit into
quinn-rs:mainfrom
fabalchemy:array-range-set-binary-search
Open

Use binary search in ArrayRangeSet#2614
fabalchemy wants to merge 1 commit into
quinn-rs:mainfrom
fabalchemy:array-range-set-binary-search

Conversation

@fabalchemy
Copy link
Copy Markdown

This PR modifies the ArrayRangeSet implementation to use binary search instead of linear scan for insertions and removals, as suggested on Discord.

I also wrote two basic criterion benchmarks:

  • completely random insertions and removals between 0 and size
  • almost-linear insertions between 0 and size with occasional holes

But did not include them in this PR since I'm not sure they're super meaningful and require a bunch of noisy diffs in quinn-proto to expose the types for the benchmarks.

They show limited gains (but no regression) for smaller sets, but significant improvements for larger sets, especially for the linear scenario which I believe is closer to the expected usage in quinn.

Size Mode BTree Array (linear scan) Array (binary search)
100 Random 14.431 µs 4.7897 µs 4.5871 µs
100 Linear 13.288 µs 4.9711 µs 4.2885 µs
500 Random 95.934 µs 46.976 µs 25.327 µs
500 Linear 84.387 µs 56.173 µs 22.717 µs
5000 Random 1.2510 ms 3.0309 ms 378.20 µs
5000 Linear 1.0457 ms 3.8295 ms 256.83 µs
10000 Random 2.6267 ms 11.886 ms 1.0308 ms
10000 Linear 2.1992 ms 13.944 ms 533.71 µs

@fabalchemy fabalchemy force-pushed the array-range-set-binary-search branch from bdaedf6 to 51517f2 Compare April 20, 2026 08:43
@Ralith
Copy link
Copy Markdown
Collaborator

Ralith commented Apr 22, 2026

Nice use of partition_point!

Does this have a statistically significant impact on e2e benchmarks? The microbenchmark results look great, but I want to be sure we're not pessimizing real-world workloads, which may not be fairly represented by bulk inserts.

@fabalchemy
Copy link
Copy Markdown
Author

I ran the quinn benchmarks on my machine and it seems this change has no impact.

I'm a bit surprised by the noise, but this is expected judging by other PRs.

Linear scan:

test large_data_10_streams  ... bench:  20,074,834 ns/iter (+/- 7,122,084) = 522 MB/s
test large_data_1_stream    ... bench:   1,995,283 ns/iter (+/- 3,274,522) = 525 MB/s
test small_data_100_streams ... bench:  13,939,785 ns/iter (+/- 30,021,101)
test small_data_1_stream    ... bench:  28,819,057 ns/iter (+/- 11,289,925)

Binary search:

test large_data_10_streams  ... bench:  19,686,293 ns/iter (+/- 5,402,187) = 532 MB/s
test large_data_1_stream    ... bench:   1,948,904 ns/iter (+/- 3,207,186) = 538 MB/s
test small_data_100_streams ... bench:  14,169,080 ns/iter (+/- 37,016,181)
test small_data_1_stream    ... bench:  29,511,801 ns/iter (+/- 10,850,156)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants