From f4c1017d0bceb49b8fb8b99865e3c4da6e4d2614 Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Mon, 24 Aug 2026 22:15:19 +0200 Subject: pkgs/fish-patched: Improve performance and reduce stutters --- ...tle-Do-more-work-in-the-command-handler-w.patch | 188 +++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 pkgs/by-name/fi/fish-patched/patches/0009-history-turtle-Do-more-work-in-the-command-handler-w.patch (limited to 'pkgs/by-name/fi/fish-patched/patches/0009-history-turtle-Do-more-work-in-the-command-handler-w.patch') diff --git a/pkgs/by-name/fi/fish-patched/patches/0009-history-turtle-Do-more-work-in-the-command-handler-w.patch b/pkgs/by-name/fi/fish-patched/patches/0009-history-turtle-Do-more-work-in-the-command-handler-w.patch new file mode 100644 index 00000000..9e5fbecc --- /dev/null +++ b/pkgs/by-name/fi/fish-patched/patches/0009-history-turtle-Do-more-work-in-the-command-handler-w.patch @@ -0,0 +1,188 @@ +From b316b4952d46ad964aa8397f9a3e57de8ba98b3b Mon Sep 17 00:00:00 2001 +From: Benedikt Peetz +Date: Mon, 24 Aug 2026 21:43:45 +0200 +Subject: [PATCH 09/10] history/turtle: Do more work in the command handler, + when loading history + +--- + src/history/turtle.rs | 94 +++++++++++++++++++++++++++++-------------- + 1 file changed, 63 insertions(+), 31 deletions(-) + +diff --git a/src/history/turtle.rs b/src/history/turtle.rs +index 4ac931a19..15515fe15 100644 +--- a/src/history/turtle.rs ++++ b/src/history/turtle.rs +@@ -5,7 +5,7 @@ + atomic::{AtomicBool, Ordering}, + mpsc, + }, +- thread::{self, JoinHandle, Thread}, ++ thread::JoinHandle, + time::{Duration, SystemTime, UNIX_EPOCH}, + }; + +@@ -19,30 +19,40 @@ + + pub(crate) struct HistoryDb; + ++#[derive(Debug, Clone)] ++struct LoadedHistory { ++ map: HashMap, ++ ++ /// This field is effectively the same as `map.keys().collect()`. ++ /// ++ /// It just a cache. ++ keys: Vec, ++} ++ + #[derive(Debug)] + struct HistoryDbInner { + range: Option, + session: uuid::Uuid, + +- loaded_history: Vec, ++ loaded_history: LoadedHistory, + + handler: Handler, + } + + impl HistoryDbInner { +- fn loaded_history(&mut self) -> &[History] { ++ fn loaded_history(&mut self) -> &LoadedHistory { + if NEW_LOADED_HISTORY_AVAILABLE.load(Ordering::Relaxed) { + if let Some(pre_loaded_history) = self.handler.load_history_resp() { + self.loaded_history = pre_loaded_history; + + // PERFORMANCE: That seems to improve performance? <2026-08-24> +- self.loaded_history.reverse(); ++ self.loaded_history.keys.reverse(); + } + + flogf!( + history, + "Loaded history was requested, returning %d entries.", +- self.loaded_history.len() ++ self.loaded_history.map.len() + ); + + NEW_LOADED_HISTORY_AVAILABLE.store(false, Ordering::Relaxed); +@@ -73,14 +83,7 @@ pub(super) fn create_empty() -> Self { + + /// Return the offsets of items in this file. + pub(super) fn offsets(&self) -> Vec { +- let out: Vec<_> = Self::with_inner_mut(|inner| { +- inner +- .loaded_history() +- .iter() +- .map(|h| h.id.clone()) +- .collect() +- }); +- out ++ Self::with_inner_mut(|inner| inner.loaded_history().keys.clone()) + } + + /// Return whether this file is empty. +@@ -111,7 +114,10 @@ pub(super) fn load(history_path: &WString, _boundary_timestamp: SystemTime) -> S + let inner = HistoryDbInner { + session: uuid::Uuid::now_v7(), + range, +- loaded_history: vec![], ++ loaded_history: LoadedHistory { ++ map: HashMap::new(), ++ keys: vec![], ++ }, + handler, + }; + +@@ -128,20 +134,7 @@ pub(super) fn load(history_path: &WString, _boundary_timestamp: SystemTime) -> S + + /// Decode an item at a given offset. + pub(super) fn decode_item(&self, id: HistoryId) -> Option { +- Self::with_inner_mut(|inner| { +- inner.loaded_history().iter().find(|h| h.id == id).map(|h| { +- HistoryItem::new( +- WString::from_str(&h.command), +- super::Timestamps { +- last_added: UNIX_EPOCH +- + Duration::from_nanos_u128(h.timestamp.unix_timestamp_nanos() as u128), +- first_added: UNIX_EPOCH +- + Duration::from_nanos_u128(h.timestamp.unix_timestamp_nanos() as u128), +- }, +- super::PersistenceMode::Disk, +- ) +- }) +- }) ++ Self::with_inner_mut(|inner| inner.loaded_history().map.get(&id).map(ToOwned::to_owned)) + } + } + +@@ -209,7 +202,7 @@ struct Handler { + + cmd_tx: Option>, + +- returned_loaded_history: Arc>>>, ++ returned_loaded_history: Arc>>, + } + + #[derive(Debug)] +@@ -311,8 +304,47 @@ fn start(daemon_socket: String) -> Self { + base.expect("the client to still work") + }; + ++ let mut loaded_history_map = HashMap::new(); ++ ++ for item in loaded_history { ++ loaded_history_map.insert(item.id, { ++ HistoryItem::new( ++ WString::from_str(&item.command), ++ super::Timestamps { ++ last_added: UNIX_EPOCH ++ + Duration::from_nanos_u128( ++ item.timestamp.unix_timestamp_nanos() as u128, ++ ), ++ first_added: UNIX_EPOCH ++ + Duration::from_nanos_u128( ++ item.timestamp.unix_timestamp_nanos() as u128, ++ ), ++ }, ++ super::PersistenceMode::Disk, ++ ) ++ }); ++ } ++ ++ let keys = { ++ let mut base: Vec<_> = loaded_history_map ++ .iter() ++ .map(|(key, h)| (key, h.first_added_timestamp())) ++ .collect(); ++ ++ base.sort_by_key(|(_, time)| *time); ++ ++ // reverse this first here, so we can re-reverse it in the ++ // `loaded_history` function. ++ base.reverse(); ++ ++ base.into_iter().map(|(key, _)| key).copied().collect() ++ }; ++ + let mut output = loaded_history_return.write().expect("not poisioned"); +- (*output) = Some(loaded_history); ++ (*output) = Some(LoadedHistory { ++ keys, ++ map: loaded_history_map, ++ }); + NEW_LOADED_HISTORY_AVAILABLE.store(true, Ordering::Relaxed); + } + } +@@ -343,7 +375,7 @@ fn stop(&mut self) { + flog!(history, "History db shutdown completed."); + } + +- fn load_history_resp(&self) -> Option> { ++ fn load_history_resp(&self) -> Option { + let mut output = None; + let rx = &self.returned_loaded_history; + +-- +2.55.0 + -- cgit v1.3.1