From 1c6dbe02ae5277caebea61929485ae4b9250a0bd Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 2 Sep 2024 02:07:34 +0200 Subject: [PATCH] editor: Do not lay out task indicators outside of the viewport (#17250) A friend of mine shared a Rust file with me that crashed Zed consistently due to Arena space exhaustion. It is a dump of a proc macro output that generates tests (among other things). TL;DR: we were always laying out all run indicators, irrespective of current scroll position. In his case, we were redundantly rendering about 3k elements. Obviously, this doesn't just fix the problems with Arena space exhaustion - it should also improve perf in files with many runnables. Release Notes: - Improved editor performance in presence of many runnable indicators in the gutter. --- crates/editor/src/element.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 12f030602b9891dc7c98d86258b2d9f64781e2f6..3abe5ee2a068970b9b393fab7a9ad869c83fdb84 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1590,6 +1590,7 @@ impl EditorElement { fn layout_run_indicators( &self, line_height: Pixels, + range: Range, scroll_pixel_position: gpui::Point, gutter_dimensions: &GutterDimensions, gutter_hitbox: &Hitbox, @@ -1613,16 +1614,20 @@ impl EditorElement { } else { None }; + editor .tasks .iter() .filter_map(|(_, tasks)| { let multibuffer_point = tasks.offset.0.to_point(&snapshot.buffer_snapshot); let multibuffer_row = MultiBufferRow(multibuffer_point.row); + let display_row = multibuffer_point.to_display_point(snapshot).row(); + if range.start > display_row || range.end < display_row { + return None; + } if snapshot.is_line_folded(multibuffer_row) { return None; } - let display_row = multibuffer_point.to_display_point(snapshot).row(); let button = editor.render_run_indicator( &self.style, Some(display_row) == active_task_indicator_row, @@ -5489,6 +5494,7 @@ impl Element for EditorElement { let test_indicators = if gutter_settings.runnables { self.layout_run_indicators( line_height, + start_row..end_row, scroll_pixel_position, &gutter_dimensions, &gutter_hitbox, @@ -5499,7 +5505,6 @@ impl Element for EditorElement { } else { Vec::new() }; - let close_indicators = self.layout_hunk_diff_close_indicators( line_height, scroll_pixel_position,