editor: Optimize selection overlap checking with binary search (#39773)

Replace O(n²) linear search with O(log n) binary search for checking
selection overlaps when finding next selection range. Pre-sort selection
ranges and use binary search to significantly improve performance when
working with many selections.

Release Notes:

- N/A

---------

Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
This commit is contained in:
Xiaobo Liu
2025-10-13 10:54:53 +02:00
committed by GitHub
parent 1ca2f9871e
commit 47a66c938f
+18 -5
View File
@@ -14448,6 +14448,10 @@ impl Editor {
let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
let mut next_selected_range = None;
// Collect and sort selection ranges for efficient overlap checking
let mut selection_ranges: Vec<_> = selections.iter().map(|s| s.range()).collect();
selection_ranges.sort_by_key(|r| r.start);
let bytes_after_last_selection =
buffer.bytes_in_range(last_selection.end..buffer.len());
let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
@@ -14469,11 +14473,20 @@ impl Editor {
|| (!buffer.is_inside_word(offset_range.start, None)
&& !buffer.is_inside_word(offset_range.end, None))
{
// TODO: This is n^2, because we might check all the selections
if !selections
.iter()
.any(|selection| selection.range().overlaps(&offset_range))
{
// Use binary search to check for overlap (O(log n))
let overlaps = selection_ranges
.binary_search_by(|range| {
if range.end <= offset_range.start {
std::cmp::Ordering::Less
} else if range.start >= offset_range.end {
std::cmp::Ordering::Greater
} else {
std::cmp::Ordering::Equal
}
})
.is_ok();
if !overlaps {
next_selected_range = Some(offset_range);
break;
}