perf(toplevel_info): optimize send_toplevel_to_client
PR #1279 tried to throttle `send_toplevel_to_client`, which was rejected. This takes (what I think is) a better approach, and instead makes some optimizations. We delay grabbing the mutex until it's actually needed, and we also checks to see if the state actually needs to be resent. This resolves some lock contention, and also avoids having to generate the state in the first place. Since `wayland-rs` uses a single mutex to lock the entire state, this both massively reduces lock contention and avoids making (apparently quite a lot of) unnecessary computation. I decided to give this one to AI since I'm a bit busy right now (although I am still manually writing the commit messages and descriptions). I think it generally did a pretty good job, although I did have to make a few manual tweaks. While I don't have any empirical data, cosmic-comp idle CPU has gone down from ~3% all-core to 0-0.5%, even stress testing it with far more windows open. I can't say it *liked* opening 30-some windows in 2 seconds, but after it finished opening them all, it was still buttery smooth. Overall very happy with the results. Assisted-by: Claude:claude-4-opus
This commit is contained in:
parent
db0b1afeb5
commit
d4c5714c10
1 changed files with 85 additions and 52 deletions
|
|
@ -495,35 +495,18 @@ where
|
|||
.unwrap()
|
||||
.lock()
|
||||
.unwrap();
|
||||
let foreign_toplevel_handle = state.foreign_handle.as_ref();
|
||||
let mut changed = false;
|
||||
|
||||
if handle_state.title != window.title() {
|
||||
handle_state.title = window.title();
|
||||
if instance.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||
instance.title(handle_state.title.clone());
|
||||
}
|
||||
if let Some(handle) = foreign_toplevel_handle {
|
||||
handle.send_title(&handle_state.title);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if handle_state.app_id != window.app_id() {
|
||||
handle_state.app_id = window.app_id();
|
||||
if instance.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||
instance.app_id(handle_state.app_id.clone());
|
||||
}
|
||||
if let Some(handle) = foreign_toplevel_handle {
|
||||
handle.send_app_id(&handle_state.app_id);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
let new_title = (handle_state.title != window.title()).then(|| window.title());
|
||||
let new_app_id = (handle_state.app_id != window.app_id()).then(|| window.app_id());
|
||||
|
||||
if handle_state.states.as_ref().is_none_or(|states| {
|
||||
let new_states = if handle_state.states.as_ref().is_none_or(|states| {
|
||||
(states.contains(&States::Maximized) != window.is_maximized())
|
||||
|| (states.contains(&States::Fullscreen) != window.is_fullscreen())
|
||||
|| (states.contains(&States::Activated) != window.is_activated())
|
||||
|| (states.contains(&States::Minimized) != window.is_minimized())
|
||||
|| (instance.version() >= zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE
|
||||
&& states.contains(&States::Sticky) != window.is_sticky())
|
||||
}) {
|
||||
let mut states = Vec::new();
|
||||
if window.is_maximized() {
|
||||
|
|
@ -543,8 +526,64 @@ where
|
|||
{
|
||||
states.push(States::Sticky);
|
||||
}
|
||||
handle_state.states = Some(states.clone());
|
||||
Some(states)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let geometry_changed = if !window.is_resizing() {
|
||||
let geometry = window.global_geometry();
|
||||
if handle_state.geometry != geometry {
|
||||
handle_state.geometry = geometry;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let outputs_changed = state.outputs != handle_state.outputs
|
||||
|| handle_state.wl_outputs.iter().any(|o| !o.is_alive());
|
||||
|
||||
let workspaces_changed = state.workspaces != handle_state.workspaces;
|
||||
|
||||
if new_title.is_none()
|
||||
&& new_app_id.is_none()
|
||||
&& new_states.is_none()
|
||||
&& !geometry_changed
|
||||
&& !outputs_changed
|
||||
&& !workspaces_changed
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let foreign_toplevel_handle = state.foreign_handle.as_ref();
|
||||
|
||||
if let Some(title) = new_title {
|
||||
handle_state.title = title;
|
||||
if instance.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||
instance.title(handle_state.title.clone());
|
||||
}
|
||||
if let Some(handle) = foreign_toplevel_handle {
|
||||
handle.send_title(&handle_state.title);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if let Some(app_id) = new_app_id {
|
||||
handle_state.app_id = app_id;
|
||||
if instance.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||
instance.app_id(handle_state.app_id.clone());
|
||||
}
|
||||
if let Some(handle) = foreign_toplevel_handle {
|
||||
handle.send_app_id(&handle_state.app_id);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if let Some(states) = new_states {
|
||||
handle_state.states = Some(states.clone());
|
||||
let states = states
|
||||
.iter()
|
||||
.flat_map(|state| (*state as u32).to_ne_bytes())
|
||||
|
|
@ -553,17 +592,9 @@ where
|
|||
changed = true;
|
||||
}
|
||||
|
||||
let mut geometry_changed = false;
|
||||
if !window.is_resizing() {
|
||||
let geometry = window.global_geometry();
|
||||
if handle_state.geometry != geometry {
|
||||
handle_state.geometry = geometry;
|
||||
changed = true;
|
||||
geometry_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(client) = dh.get_client(instance.id()) {
|
||||
if (outputs_changed || geometry_changed)
|
||||
&& let Ok(client) = dh.get_client(instance.id())
|
||||
{
|
||||
handle_state.outputs = state.outputs.clone();
|
||||
|
||||
let handle_state = &mut *handle_state;
|
||||
|
|
@ -599,27 +630,29 @@ where
|
|||
});
|
||||
}
|
||||
|
||||
for new_workspace in state
|
||||
.workspaces
|
||||
.iter()
|
||||
.filter(|w| !handle_state.workspaces.contains(w))
|
||||
{
|
||||
for handle in workspace_state.raw_ext_workspace_handles(new_workspace, &instance.id()) {
|
||||
instance.ext_workspace_enter(handle);
|
||||
changed = true;
|
||||
if workspaces_changed {
|
||||
for new_workspace in state
|
||||
.workspaces
|
||||
.iter()
|
||||
.filter(|w| !handle_state.workspaces.contains(w))
|
||||
{
|
||||
for handle in workspace_state.raw_ext_workspace_handles(new_workspace, &instance.id()) {
|
||||
instance.ext_workspace_enter(handle);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for old_workspace in handle_state
|
||||
.workspaces
|
||||
.iter()
|
||||
.filter(|w| !state.workspaces.contains(w))
|
||||
{
|
||||
for handle in workspace_state.raw_ext_workspace_handles(old_workspace, &instance.id()) {
|
||||
instance.ext_workspace_leave(handle);
|
||||
changed = true;
|
||||
for old_workspace in handle_state
|
||||
.workspaces
|
||||
.iter()
|
||||
.filter(|w| !state.workspaces.contains(w))
|
||||
{
|
||||
for handle in workspace_state.raw_ext_workspace_handles(old_workspace, &instance.id()) {
|
||||
instance.ext_workspace_leave(handle);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
handle_state.workspaces = state.workspaces.clone();
|
||||
}
|
||||
handle_state.workspaces = state.workspaces.clone();
|
||||
|
||||
if changed {
|
||||
if instance.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue