From 6b9a0843fd2eb186d53369ee6d8d47ec4c95fd59 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Sun, 9 Jun 2024 07:13:18 -0700 Subject: [PATCH] perf(borders): introduce state snapshot checks This commit introduce state snapshot checks in the border manager, which will ensure that we don't even attempt to acquire any mutex locks if the state hasn't changed. --- komorebi-core/src/arrangement.rs | 11 ++++++++++- komorebi-core/src/custom_layout.rs | 10 +++++----- komorebi-core/src/layout.rs | 2 +- komorebi/src/border_manager/mod.rs | 20 +++++++++++++++----- komorebi/src/monitor.rs | 11 ++++++++++- komorebi/src/ring.rs | 2 +- komorebi/src/window.rs | 2 +- komorebi/src/workspace.rs | 11 ++++++++++- 8 files changed, 53 insertions(+), 16 deletions(-) diff --git a/komorebi-core/src/arrangement.rs b/komorebi-core/src/arrangement.rs index 4b15ab36..0c3b3b04 100644 --- a/komorebi-core/src/arrangement.rs +++ b/komorebi-core/src/arrangement.rs @@ -604,7 +604,16 @@ impl Arrangement for CustomLayout { } #[derive( - Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema, + Clone, + Copy, + Debug, + Serialize, + Deserialize, + Display, + EnumString, + ValueEnum, + JsonSchema, + PartialEq, )] pub enum Axis { Horizontal, diff --git a/komorebi-core/src/custom_layout.rs b/komorebi-core/src/custom_layout.rs index 2edae177..756fd652 100644 --- a/komorebi-core/src/custom_layout.rs +++ b/komorebi-core/src/custom_layout.rs @@ -14,7 +14,7 @@ use serde::Serialize; use crate::Rect; -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] pub struct CustomLayout(Vec); impl Deref for CustomLayout { @@ -250,7 +250,7 @@ impl CustomLayout { } } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] #[serde(tag = "column", content = "configuration")] pub enum Column { Primary(Option), @@ -258,18 +258,18 @@ pub enum Column { Tertiary(ColumnSplit), } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] pub enum ColumnWidth { WidthPercentage(f32), } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] pub enum ColumnSplit { Horizontal, Vertical, } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] pub enum ColumnSplitWithCapacity { Horizontal(usize), Vertical(usize), diff --git a/komorebi-core/src/layout.rs b/komorebi-core/src/layout.rs index 023d41c8..f22dd8a4 100644 --- a/komorebi-core/src/layout.rs +++ b/komorebi-core/src/layout.rs @@ -7,7 +7,7 @@ use crate::CustomLayout; use crate::DefaultLayout; use crate::Direction; -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] pub enum Layout { Default(DefaultLayout), Custom(CustomLayout), diff --git a/komorebi/src/border_manager/mod.rs b/komorebi/src/border_manager/mod.rs index 6803f6f6..c8932646 100644 --- a/komorebi/src/border_manager/mod.rs +++ b/komorebi/src/border_manager/mod.rs @@ -21,6 +21,7 @@ use std::sync::Arc; use std::sync::OnceLock; use windows::Win32::Foundation::HWND; +use crate::ring::Ring; use crate::workspace_reconciliator::ALT_TAB_HWND; use crate::Colour; use crate::Rgb; @@ -121,18 +122,25 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result let receiver = event_rx(); event_tx().send(Notification)?; - 'receiver: for _ in receiver { - let mut borders = BORDER_STATE.lock(); - let mut borders_monitors = BORDERS_MONITORS.lock(); + let mut latest_snapshot = Ring::default(); + 'receiver: for _ in receiver { // Check the wm state every time we receive a notification let state = wm.lock(); let is_paused = state.is_paused; let focused_monitor_idx = state.focused_monitor_idx(); - let monitors = state.monitors.elements().clone(); + let monitors = state.monitors.clone(); let pending_move_op = state.pending_move_op; drop(state); + if monitors == latest_snapshot { + tracing::trace!("monitor state matches latest snapshot, skipping notification"); + continue 'receiver; + } + + let mut borders = BORDER_STATE.lock(); + let mut borders_monitors = BORDERS_MONITORS.lock(); + // If borders are disabled if !BORDER_ENABLED.load_consume() // Or if the wm is paused @@ -149,7 +157,7 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result continue 'receiver; } - 'monitors: for (monitor_idx, m) in monitors.iter().enumerate() { + 'monitors: for (monitor_idx, m) in monitors.elements().iter().enumerate() { // Only operate on the focused workspace of each monitor if let Some(ws) = m.focused_workspace() { // Workspaces with tiling disabled don't have borders @@ -337,6 +345,8 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result } } } + + latest_snapshot = monitors; } Ok(()) diff --git a/komorebi/src/monitor.rs b/komorebi/src/monitor.rs index 162ac526..ff708ede 100644 --- a/komorebi/src/monitor.rs +++ b/komorebi/src/monitor.rs @@ -19,7 +19,16 @@ use crate::ring::Ring; use crate::workspace::Workspace; #[derive( - Debug, Clone, Serialize, Deserialize, Getters, CopyGetters, MutGetters, Setters, JsonSchema, + Debug, + Clone, + Serialize, + Deserialize, + Getters, + CopyGetters, + MutGetters, + Setters, + JsonSchema, + PartialEq, )] pub struct Monitor { #[getset(get_copy = "pub", set = "pub")] diff --git a/komorebi/src/ring.rs b/komorebi/src/ring.rs index d5da1698..325b9065 100644 --- a/komorebi/src/ring.rs +++ b/komorebi/src/ring.rs @@ -4,7 +4,7 @@ use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] pub struct Ring { elements: VecDeque, focused: usize, diff --git a/komorebi/src/window.rs b/komorebi/src/window.rs index d56464f1..9e513ca4 100644 --- a/komorebi/src/window.rs +++ b/komorebi/src/window.rs @@ -39,7 +39,7 @@ use crate::PERMAIGNORE_CLASSES; use crate::REGEX_IDENTIFIERS; use crate::WSL2_UI_PROCESSES; -#[derive(Debug, Default, Clone, Copy, Deserialize, JsonSchema)] +#[derive(Debug, Default, Clone, Copy, Deserialize, JsonSchema, PartialEq)] pub struct Window { pub hwnd: isize, } diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index eaf43972..5c8debb5 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -38,7 +38,16 @@ use crate::REMOVE_TITLEBARS; #[allow(clippy::struct_field_names)] #[derive( - Debug, Clone, Serialize, Deserialize, Getters, CopyGetters, MutGetters, Setters, JsonSchema, + Debug, + Clone, + Serialize, + Deserialize, + Getters, + CopyGetters, + MutGetters, + Setters, + JsonSchema, + PartialEq, )] pub struct Workspace { #[getset(get = "pub", set = "pub")]