From a5c69beabfc82d9c3f9563eb821139b2e0f3e14f Mon Sep 17 00:00:00 2001 From: Can Celik Date: Wed, 19 Aug 2026 04:43:28 +0300 Subject: fix(perf): eliminate redundant terminal wake work (#2962) * fix(perf): eliminate redundant terminal wake work * fix(perf): harden release benchmark gate * test(perf): strengthen performance guardrails --- src/server/headless.rs | 66 +++++++++++++++++++++++++++---------------- src/server/terminal_attach.rs | 6 +--- 2 files changed, 42 insertions(+), 30 deletions(-) (limited to 'src/server') diff --git a/src/server/headless.rs b/src/server/headless.rs index ae0d7b20..9161cd34 100644 --- a/src/server/headless.rs +++ b/src/server/headless.rs @@ -357,8 +357,8 @@ fn apply_terminal_attach_scroll( }; if let AttachScrollSource::PageKey { input } = source { let host_scroll = runtime - .input_state() - .is_some_and(crate::pane::InputState::plain_page_keys_use_host_scrollback); + .plain_page_keys_use_host_scrollback() + .unwrap_or(false); if host_scroll { match direction { AttachScrollDirection::Up => runtime.scroll_up(lines.max(1) as usize), @@ -695,6 +695,7 @@ impl HeadlessServer { } self.drain_client_config_reload_request(); + self.sync_immediate_pty_sources(); self.stream_host_mouse_capture_mode(); self.stream_host_keyboard_enhancement_flags(); @@ -3998,10 +3999,7 @@ impl HeadlessServer { ) }) }) - .and_then(crate::terminal::TerminalRuntime::input_state) - .is_some_and(|state| { - state.mouse_protocol_encoding == crate::input::MouseProtocolEncoding::SgrPixels - }); + .is_some_and(crate::terminal::TerminalRuntime::sgr_pixel_mouse_enabled); let mut broken_clients: Vec = Vec::new(); for (&client_id, client) in &mut self.clients { if !client.is_full_app_client() { @@ -4086,24 +4084,33 @@ impl HeadlessServer { needs_full_render: bool, needs_graphics_render: bool, ) -> bool { - if needs_full_render - || needs_graphics_render - || self.app.render_dirty.has_generic_or_terminal_title() - { - return true; - } + needs_full_render || needs_graphics_render || self.app.render_dirty.has_immediate_work() + } + fn sync_immediate_pty_sources(&self) { let (has_app_target, direct_terminal_targets) = self.pty_render_targets(); - if !has_app_target && direct_terminal_targets.is_empty() { - return false; + let mut pane_ids = if has_app_target { + self.app.state.app_surface_pane_ids() + } else { + HashSet::new() + }; + if !direct_terminal_targets.is_empty() { + for workspace in &self.app.state.workspaces { + for tab in &workspace.tabs { + pane_ids.extend(tab.panes.iter().filter_map(|(&pane_id, pane)| { + direct_terminal_targets + .contains(pane.attached_terminal_id.as_str()) + .then_some(pane_id) + })); + } + } + if let Some(popup) = &self.app.state.popup_pane { + if direct_terminal_targets.contains(popup.terminal_id.as_str()) { + pane_ids.insert(popup.pane_id); + } + } } - self.app.render_dirty.has_pty_source_matching(|pane_id| { - self.pty_source_visible_to_render_targets( - pane_id, - has_app_target, - &direct_terminal_targets, - ) - }) + self.app.render_dirty.set_immediate_pty_sources(pane_ids); } fn pty_render_targets(&self) -> (bool, HashSet<&str>) { @@ -9684,6 +9691,7 @@ next_tab = "" fn visible_source_wakes_pending_hidden_work() { let (server, background_pane) = hidden_pty_visibility_test_server(&[(120, 40)]); let visible_pane = server.app.state.workspaces[0].tabs[0].root_pane; + server.sync_immediate_pty_sources(); assert!(server.app.render_dirty.request_pty(background_pane)); assert!(!server.has_pending_presentation_work(false, false)); @@ -9776,15 +9784,17 @@ next_tab = "" } #[test] - fn direct_terminal_observer_keeps_hidden_pty_source_renderable() { - let (mut server, background_pane) = hidden_pty_visibility_test_server(&[]); + fn direct_terminal_observer_keeps_hidden_pty_source_renderable_with_app_client() { + let (mut server, background_pane) = hidden_pty_visibility_test_server(&[(120, 40)]); + assert!(!server.pty_sources_visible_to_any_render_target(&HashSet::from([background_pane]))); + let terminal_id = server.app.state.workspaces[0] .terminal_id(background_pane) .expect("background terminal id") .to_string(); let (client_tx, _client_control_rx, _client_rx) = test_client_writer(); server.clients.insert( - 1, + 2, ClientConnection::new_with_mode( ClientConnectionMode::TerminalObserve { terminal_id }, None, @@ -9792,7 +9802,7 @@ next_tab = "" crate::kitty_graphics::HostCellSize::default(), crate::terminal_theme::TerminalTheme::default(), None, - 1, + 2, RenderEncoding::SemanticFrame, false, Some(client_tx), @@ -9800,6 +9810,12 @@ next_tab = "" ); assert!(server.pty_sources_visible_to_any_render_target(&HashSet::from([background_pane]))); + + let hidden_pane = server.app.state.workspaces[0].tabs[0].root_pane; + server.sync_immediate_pty_sources(); + assert!(server.app.render_dirty.request_pty(background_pane)); + assert!(server.has_pending_presentation_work(false, false)); + assert!(server.app.render_dirty.request_pty(hidden_pane)); } #[tokio::test] diff --git a/src/server/terminal_attach.rs b/src/server/terminal_attach.rs index 01fc899f..e7a52be5 100644 --- a/src/server/terminal_attach.rs +++ b/src/server/terminal_attach.rs @@ -2,11 +2,7 @@ pub(crate) fn paste_payload_for_runtime( runtime: &crate::terminal::TerminalRuntime, text: &str, ) -> String { - if runtime - .input_state() - .map(|state| state.bracketed_paste) - .unwrap_or(false) - { + if runtime.bracketed_paste_enabled() { format!("\x1b[200~{text}\x1b[201~") } else { text.to_owned() -- cgit v1.2.3