Fix lag when large diff hunk intersects the viewport (#26088)

We were iterating over the row range of a hunk, and inserting into a
hash map for every row.

Release Notes:

- Fixed a performance problem when a large diff hunk was displayed in an
editor.
This commit is contained in:
Max Brunsfeld 2025-03-04 16:25:58 -08:00 committed by GitHub
parent befacfe8c9
commit fe18c73a07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2018,7 +2018,7 @@ impl EditorElement {
scroll_pixel_position: gpui::Point<Pixels>,
gutter_dimensions: &GutterDimensions,
gutter_hitbox: &Hitbox,
rows_with_hunk_bounds: &HashMap<DisplayRow, Bounds<Pixels>>,
display_hunks: &[(DisplayDiffHunk, Option<Hitbox>)],
snapshot: &EditorSnapshot,
window: &mut Window,
cx: &mut App,
@ -2094,7 +2094,7 @@ impl EditorElement {
gutter_dimensions,
scroll_pixel_position,
gutter_hitbox,
rows_with_hunk_bounds,
display_hunks,
window,
cx,
);
@ -2112,7 +2112,7 @@ impl EditorElement {
scroll_pixel_position: gpui::Point<Pixels>,
gutter_dimensions: &GutterDimensions,
gutter_hitbox: &Hitbox,
rows_with_hunk_bounds: &HashMap<DisplayRow, Bounds<Pixels>>,
display_hunks: &[(DisplayDiffHunk, Option<Hitbox>)],
window: &mut Window,
cx: &mut App,
) -> Option<AnyElement> {
@ -2137,7 +2137,7 @@ impl EditorElement {
gutter_dimensions,
scroll_pixel_position,
gutter_hitbox,
rows_with_hunk_bounds,
display_hunks,
window,
cx,
);
@ -5689,7 +5689,7 @@ fn prepaint_gutter_button(
gutter_dimensions: &GutterDimensions,
scroll_pixel_position: gpui::Point<Pixels>,
gutter_hitbox: &Hitbox,
rows_with_hunk_bounds: &HashMap<DisplayRow, Bounds<Pixels>>,
display_hunks: &[(DisplayDiffHunk, Option<Hitbox>)],
window: &mut Window,
cx: &mut App,
) -> AnyElement {
@ -5701,9 +5701,23 @@ fn prepaint_gutter_button(
let indicator_size = button.layout_as_root(available_space, window, cx);
let blame_width = gutter_dimensions.git_blame_entries_width;
let gutter_width = rows_with_hunk_bounds
.get(&row)
.map(|bounds| bounds.size.width);
let gutter_width = display_hunks
.binary_search_by(|(hunk, _)| match hunk {
DisplayDiffHunk::Folded { display_row } => display_row.cmp(&row),
DisplayDiffHunk::Unfolded {
display_row_range, ..
} => {
if display_row_range.end <= row {
Ordering::Less
} else if display_row_range.start > row {
Ordering::Greater
} else {
Ordering::Equal
}
}
})
.ok()
.and_then(|ix| Some(display_hunks[ix].1.as_ref()?.size.width));
let left_offset = blame_width.max(gutter_width).unwrap_or_default();
let mut x = left_offset;
@ -7219,27 +7233,6 @@ impl Element for EditorElement {
let gutter_settings = EditorSettings::get_global(cx).gutter;
let rows_with_hunk_bounds = display_hunks
.iter()
.filter_map(|(hunk, hitbox)| Some((hunk, hitbox.as_ref()?.bounds)))
.fold(
HashMap::default(),
|mut rows_with_hunk_bounds, (hunk, bounds)| {
match hunk {
DisplayDiffHunk::Folded { display_row } => {
rows_with_hunk_bounds.insert(*display_row, bounds);
}
DisplayDiffHunk::Unfolded {
display_row_range, ..
} => {
for display_row in display_row_range.iter_rows() {
rows_with_hunk_bounds.insert(display_row, bounds);
}
}
}
rows_with_hunk_bounds
},
);
let mut code_actions_indicator = None;
if let Some(newest_selection_head) = newest_selection_head {
let newest_selection_point =
@ -7289,7 +7282,7 @@ impl Element for EditorElement {
scroll_pixel_position,
&gutter_dimensions,
&gutter_hitbox,
&rows_with_hunk_bounds,
&display_hunks,
window,
cx,
);
@ -7317,7 +7310,7 @@ impl Element for EditorElement {
scroll_pixel_position,
&gutter_dimensions,
&gutter_hitbox,
&rows_with_hunk_bounds,
&display_hunks,
&snapshot,
window,
cx,