editor: Improve minimap performance (#33067)
This PR aims to improve the minimap performace. This is primarily achieved by disabling/removing stuff that is not shown in the minimal as well as by assuring the display map is not updated during minimap prepaint. This should already be much better in parts, as the block map as well as the fold map will be less frequently updated due to the minimap prepainting (optimally, they should never be, but I think we're not quite there yet). For this, I had to remove block rendering support for the minimap, which is not as bad as it sounds: Practically, we were currently not rendering most blocks anyway, there were issues due to this (e.g. scrolling any visible block offscreen in the main editor causes scroll jumps currently) and in the long run, the minimap will most likely need its own block map or a different approach anyway. The existing implementation caused resizes to occur very frequently for practically no benefit. Can pull this out into a separate PR if requested, most likely makes the other changes here easier to discuss. This is WIP as we are still hitting some code path here we definitely should not be hitting. E.g. there seems to be a rerender roughly every second if the window is unfocused but visible which does not happen when the minimap is disabled. While this primarily focuses on the minimap, it also touches a few other small parts not related to the minimap where I noticed we were doing too much stuff during prepaint. Happy for any feedback there aswell. Putting this up here already so we have a place to discuss the changes early if needed. Release Notes: - Improved performance with the minimap enabled. - Fixed an issue where interacting with blocks in the editor would sometimes not properly work with the minimap enabled.
This commit is contained in:
parent
363a265051
commit
26ba6e7e00
12 changed files with 207 additions and 184 deletions
|
@ -1795,6 +1795,7 @@ impl Editor {
|
|||
);
|
||||
|
||||
let full_mode = mode.is_full();
|
||||
let is_minimap = mode.is_minimap();
|
||||
let diagnostics_max_severity = if full_mode {
|
||||
EditorSettings::get_global(cx)
|
||||
.diagnostics_max_severity
|
||||
|
@ -1855,13 +1856,19 @@ impl Editor {
|
|||
|
||||
let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
|
||||
|
||||
let blink_manager = cx.new(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
|
||||
let blink_manager = cx.new(|cx| {
|
||||
let mut blink_manager = BlinkManager::new(CURSOR_BLINK_INTERVAL, cx);
|
||||
if is_minimap {
|
||||
blink_manager.disable(cx);
|
||||
}
|
||||
blink_manager
|
||||
});
|
||||
|
||||
let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
|
||||
.then(|| language_settings::SoftWrap::None);
|
||||
|
||||
let mut project_subscriptions = Vec::new();
|
||||
if mode.is_full() {
|
||||
if full_mode {
|
||||
if let Some(project) = project.as_ref() {
|
||||
project_subscriptions.push(cx.subscribe_in(
|
||||
project,
|
||||
|
@ -1972,18 +1979,23 @@ impl Editor {
|
|||
let inlay_hint_settings =
|
||||
inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
|
||||
let focus_handle = cx.focus_handle();
|
||||
cx.on_focus(&focus_handle, window, Self::handle_focus)
|
||||
.detach();
|
||||
cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
|
||||
.detach();
|
||||
cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
|
||||
.detach();
|
||||
cx.on_blur(&focus_handle, window, Self::handle_blur)
|
||||
.detach();
|
||||
cx.observe_pending_input(window, Self::observe_pending_input)
|
||||
.detach();
|
||||
if !is_minimap {
|
||||
cx.on_focus(&focus_handle, window, Self::handle_focus)
|
||||
.detach();
|
||||
cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
|
||||
.detach();
|
||||
cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
|
||||
.detach();
|
||||
cx.on_blur(&focus_handle, window, Self::handle_blur)
|
||||
.detach();
|
||||
cx.observe_pending_input(window, Self::observe_pending_input)
|
||||
.detach();
|
||||
}
|
||||
|
||||
let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
|
||||
let show_indent_guides = if matches!(
|
||||
mode,
|
||||
EditorMode::SingleLine { .. } | EditorMode::Minimap { .. }
|
||||
) {
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
|
@ -2049,10 +2061,10 @@ impl Editor {
|
|||
minimap_visibility: MinimapVisibility::for_mode(&mode, cx),
|
||||
offset_content: !matches!(mode, EditorMode::SingleLine { .. }),
|
||||
show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
|
||||
show_gutter: mode.is_full(),
|
||||
show_line_numbers: None,
|
||||
show_gutter: full_mode,
|
||||
show_line_numbers: (!full_mode).then_some(false),
|
||||
use_relative_line_numbers: None,
|
||||
disable_expand_excerpt_buttons: false,
|
||||
disable_expand_excerpt_buttons: !full_mode,
|
||||
show_git_diff_gutter: None,
|
||||
show_code_actions: None,
|
||||
show_runnables: None,
|
||||
|
@ -2086,7 +2098,7 @@ impl Editor {
|
|||
document_highlights_task: None,
|
||||
linked_editing_range_task: None,
|
||||
pending_rename: None,
|
||||
searchable: true,
|
||||
searchable: !is_minimap,
|
||||
cursor_shape: EditorSettings::get_global(cx)
|
||||
.cursor_shape
|
||||
.unwrap_or_default(),
|
||||
|
@ -2094,9 +2106,9 @@ impl Editor {
|
|||
autoindent_mode: Some(AutoindentMode::EachLine),
|
||||
collapse_matches: false,
|
||||
workspace: None,
|
||||
input_enabled: true,
|
||||
use_modal_editing: mode.is_full(),
|
||||
read_only: mode.is_minimap(),
|
||||
input_enabled: !is_minimap,
|
||||
use_modal_editing: full_mode,
|
||||
read_only: is_minimap,
|
||||
use_autoclose: true,
|
||||
use_auto_surround: true,
|
||||
auto_replace_emoji_shortcode: false,
|
||||
|
@ -2112,11 +2124,10 @@ impl Editor {
|
|||
edit_prediction_preview: EditPredictionPreview::Inactive {
|
||||
released_too_fast: false,
|
||||
},
|
||||
inline_diagnostics_enabled: mode.is_full(),
|
||||
diagnostics_enabled: mode.is_full(),
|
||||
inline_diagnostics_enabled: full_mode,
|
||||
diagnostics_enabled: full_mode,
|
||||
inline_value_cache: InlineValueCache::new(inlay_hint_settings.show_value_hints),
|
||||
inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
|
||||
|
||||
gutter_hovered: false,
|
||||
pixel_position_of_newest_cursor: None,
|
||||
last_bounds: None,
|
||||
|
@ -2139,9 +2150,10 @@ impl Editor {
|
|||
show_git_blame_inline: false,
|
||||
show_selection_menu: None,
|
||||
show_git_blame_inline_delay_task: None,
|
||||
git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
|
||||
git_blame_inline_enabled: full_mode
|
||||
&& ProjectSettings::get_global(cx).git.inline_blame_enabled(),
|
||||
render_diff_hunk_controls: Arc::new(render_diff_hunk_controls),
|
||||
serialize_dirty_buffers: !mode.is_minimap()
|
||||
serialize_dirty_buffers: !is_minimap
|
||||
&& ProjectSettings::get_global(cx)
|
||||
.session
|
||||
.restore_unsaved_buffers,
|
||||
|
@ -2152,27 +2164,31 @@ impl Editor {
|
|||
breakpoint_store,
|
||||
gutter_breakpoint_indicator: (None, None),
|
||||
hovered_diff_hunk_row: None,
|
||||
_subscriptions: vec![
|
||||
cx.observe(&buffer, Self::on_buffer_changed),
|
||||
cx.subscribe_in(&buffer, window, Self::on_buffer_event),
|
||||
cx.observe_in(&display_map, window, Self::on_display_map_changed),
|
||||
cx.observe(&blink_manager, |_, _, cx| cx.notify()),
|
||||
cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
|
||||
observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
|
||||
cx.observe_window_activation(window, |editor, window, cx| {
|
||||
let active = window.is_window_active();
|
||||
editor.blink_manager.update(cx, |blink_manager, cx| {
|
||||
if active {
|
||||
blink_manager.enable(cx);
|
||||
} else {
|
||||
blink_manager.disable(cx);
|
||||
}
|
||||
});
|
||||
if active {
|
||||
editor.show_mouse_cursor(cx);
|
||||
}
|
||||
}),
|
||||
],
|
||||
_subscriptions: (!is_minimap)
|
||||
.then(|| {
|
||||
vec![
|
||||
cx.observe(&buffer, Self::on_buffer_changed),
|
||||
cx.subscribe_in(&buffer, window, Self::on_buffer_event),
|
||||
cx.observe_in(&display_map, window, Self::on_display_map_changed),
|
||||
cx.observe(&blink_manager, |_, _, cx| cx.notify()),
|
||||
cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
|
||||
observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
|
||||
cx.observe_window_activation(window, |editor, window, cx| {
|
||||
let active = window.is_window_active();
|
||||
editor.blink_manager.update(cx, |blink_manager, cx| {
|
||||
if active {
|
||||
blink_manager.enable(cx);
|
||||
} else {
|
||||
blink_manager.disable(cx);
|
||||
}
|
||||
});
|
||||
if active {
|
||||
editor.show_mouse_cursor(cx);
|
||||
}
|
||||
}),
|
||||
]
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
tasks_update_task: None,
|
||||
pull_diagnostics_task: Task::ready(()),
|
||||
colors: None,
|
||||
|
@ -2203,6 +2219,11 @@ impl Editor {
|
|||
selection_drag_state: SelectionDragState::None,
|
||||
folding_newlines: Task::ready(()),
|
||||
};
|
||||
|
||||
if is_minimap {
|
||||
return editor;
|
||||
}
|
||||
|
||||
if let Some(breakpoints) = editor.breakpoint_store.as_ref() {
|
||||
editor
|
||||
._subscriptions
|
||||
|
@ -10445,7 +10466,6 @@ impl Editor {
|
|||
cloned_prompt.clone().into_any_element()
|
||||
}),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
}];
|
||||
|
||||
let focus_handle = bp_prompt.focus_handle(cx);
|
||||
|
@ -16141,7 +16161,6 @@ impl Editor {
|
|||
}
|
||||
}),
|
||||
priority: 0,
|
||||
render_in_minimap: true,
|
||||
}],
|
||||
Some(Autoscroll::fit()),
|
||||
cx,
|
||||
|
@ -18044,7 +18063,7 @@ impl Editor {
|
|||
parent: cx.weak_entity(),
|
||||
},
|
||||
self.buffer.clone(),
|
||||
self.project.clone(),
|
||||
None,
|
||||
Some(self.display_map.clone()),
|
||||
window,
|
||||
cx,
|
||||
|
@ -19928,14 +19947,12 @@ impl Editor {
|
|||
}
|
||||
|
||||
fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let new_severity = if self.diagnostics_enabled() {
|
||||
EditorSettings::get_global(cx)
|
||||
if self.diagnostics_enabled() {
|
||||
let new_severity = EditorSettings::get_global(cx)
|
||||
.diagnostics_max_severity
|
||||
.unwrap_or(DiagnosticSeverity::Hint)
|
||||
} else {
|
||||
DiagnosticSeverity::Off
|
||||
};
|
||||
self.set_max_diagnostics_severity(new_severity, cx);
|
||||
.unwrap_or(DiagnosticSeverity::Hint);
|
||||
self.set_max_diagnostics_severity(new_severity, cx);
|
||||
}
|
||||
self.tasks_update_task = Some(self.refresh_runnables(window, cx));
|
||||
self.update_edit_prediction_settings(cx);
|
||||
self.refresh_inline_completion(true, false, window, cx);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue