Baseline: Improve selection rendering for large quantities from 270ms to 90ms

This commit is contained in:
Piotr Osiewicz 2023-08-07 23:32:27 +02:00
parent e3a4d174de
commit ca21626064
2 changed files with 86 additions and 45 deletions

View file

@ -90,7 +90,7 @@ use std::{
cmp::{self, Ordering, Reverse}, cmp::{self, Ordering, Reverse},
mem, mem,
num::NonZeroU32, num::NonZeroU32,
ops::{ControlFlow, Deref, DerefMut, Range}, ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
path::Path, path::Path,
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
@ -7549,6 +7549,68 @@ impl Editor {
results results
} }
pub fn selected_rows<T: 'static>(
&self,
search_range: Range<Anchor>,
display_snapshot: &DisplaySnapshot,
theme: &Theme,
) -> Vec<RangeInclusive<u32>> {
let mut results = Vec::new();
let buffer = &display_snapshot.buffer_snapshot;
let Some((color_fetcher, ranges)) = self.background_highlights
.get(&TypeId::of::<T>()) else {
return vec![];
};
let color = color_fetcher(theme);
let start_ix = match ranges.binary_search_by(|probe| {
let cmp = probe.end.cmp(&search_range.start, buffer);
if cmp.is_gt() {
Ordering::Greater
} else {
Ordering::Less
}
}) {
Ok(i) | Err(i) => i,
};
let mut push_region = |start, end| {
if let (Some(start_display), Some(end_display)) = (start, end) {
results.push(start_display..=end_display);
}
};
let mut start_row = None;
let mut end_row = None;
for range in &ranges[start_ix..] {
if range.start.cmp(&search_range.end, buffer).is_ge() {
break;
}
let start = range.start.to_point(buffer).row;
let end = range.end.to_point(buffer).row;
if start_row.is_none() {
assert_eq!(end_row, None);
start_row = Some(start);
end_row = Some(end);
continue;
}
if let Some(current_end) = end_row.as_mut() {
if start > *current_end + 1 {
push_region(start_row, end_row);
start_row = Some(start);
end_row = Some(end);
} else {
// Merge two hunks.
*current_end = end;
}
} else {
unreachable!();
}
}
// We might still have a hunk that was not rendered (if there was a search hit on the last line)
push_region(start_row, end_row);
results
}
pub fn highlight_text<T: 'static>( pub fn highlight_text<T: 'static>(
&mut self, &mut self,
ranges: Vec<Range<Anchor>>, ranges: Vec<Range<Anchor>>,

View file

@ -1107,8 +1107,6 @@ impl EditorElement {
if layout.is_singleton && scrollbar_settings.selections { if layout.is_singleton && scrollbar_settings.selections {
let start_anchor = Anchor::min(); let start_anchor = Anchor::min();
let end_anchor = Anchor::max(); let end_anchor = Anchor::max();
let mut start_row = None;
let mut end_row = None;
let color = scrollbar_theme.selections; let color = scrollbar_theme.selections;
let border = Border { let border = Border {
width: 1., width: 1.,
@ -1119,10 +1117,9 @@ impl EditorElement {
bottom: false, bottom: false,
left: true, left: true,
}; };
let mut push_region = |start, end| { let mut push_region = |start: u32, end: u32| {
if let (Some(start_display), Some(end_display)) = (start, end) { let start_y = y_for_row(start as f32);
let start_y = y_for_row(start_display as f32); let mut end_y = y_for_row(end as f32);
let mut end_y = y_for_row(end_display as f32);
if end_y - start_y < 1. { if end_y - start_y < 1. {
end_y = start_y + 1.; end_y = start_y + 1.;
} }
@ -1134,39 +1131,21 @@ impl EditorElement {
border, border,
corner_radius: style.thumb.corner_radius, corner_radius: style.thumb.corner_radius,
}) })
}
}; };
for (row, _) in &editor let start = std::time::Instant::now();
.background_highlights_in_range_for::<crate::items::BufferSearchHighlights>(
let background_ranges = editor
.selected_rows::<crate::items::BufferSearchHighlights>(
start_anchor..end_anchor, start_anchor..end_anchor,
&layout.position_map.snapshot, &layout.position_map.snapshot,
&theme, &theme,
) );
{ dbg!(start.elapsed().as_millis());
let start_display = row.start; for row in background_ranges {
let end_display = row.end; let start = row.start();
let end = row.end();
if start_row.is_none() { push_region(*start, *end);
assert_eq!(end_row, None);
start_row = Some(start_display.row());
end_row = Some(end_display.row());
continue;
} }
if let Some(current_end) = end_row.as_mut() {
if start_display.row() > *current_end + 1 {
push_region(start_row, end_row);
start_row = Some(start_display.row());
end_row = Some(end_display.row());
} else {
// Merge two hunks.
*current_end = end_display.row();
}
} else {
unreachable!();
}
}
// We might still have a hunk that was not rendered (if there was a search hit on the last line)
push_region(start_row, end_row);
} }
if layout.is_singleton && scrollbar_settings.git_diff { if layout.is_singleton && scrollbar_settings.git_diff {