Coalesce idempotent refreshSession calls triggered by event handlers#1249
Closed
rickyz wants to merge 1 commit intonikitabobko:mainfrom
Closed
Coalesce idempotent refreshSession calls triggered by event handlers#1249rickyz wants to merge 1 commit intonikitabobko:mainfrom
rickyz wants to merge 1 commit intonikitabobko:mainfrom
Conversation
f87217e to
da0cc06
Compare
On operations like workspace changes, AeroSpace receives a stampede of accessibility events, each of which triggers a serial call to `refreshSession()` on the main thread. Since these `refreshSession()` calls are idempotent, we can coalesce these calls so that multiple accessibility events can be handled by a single `refreshSession()`. With this change, operations like workspace switch go from O(num_source_windows + num_dest_windows) to O(1) `refreshSession()` calls (with similar improvements for operations like closing windows or resizing windows).
da0cc06 to
e8e2efa
Compare
nikitabobko
reviewed
Apr 1, 2025
Comment on lines
+56
to
+59
| if screenIsDefinitelyUnlocked { | ||
| pendingRefreshScreenIsDefinitelyUnlocked = true | ||
| } | ||
| return |
Owner
nikitabobko
reviewed
Apr 1, 2025
Comment on lines
+55
to
+62
| if havePendingRefresh { | ||
| if screenIsDefinitelyUnlocked { | ||
| pendingRefreshScreenIsDefinitelyUnlocked = true | ||
| } | ||
| return | ||
| } | ||
| havePendingRefresh = true | ||
| pendingRefreshScreenIsDefinitelyUnlocked = screenIsDefinitelyUnlocked |
Owner
There was a problem hiding this comment.
It feels more natural to me to coalesce the latest screenIsDefinitelyUnlocked state into pendingRefreshScreenIsDefinitelyUnlocked in whatever case:
Suggested change
| if havePendingRefresh { | |
| if screenIsDefinitelyUnlocked { | |
| pendingRefreshScreenIsDefinitelyUnlocked = true | |
| } | |
| return | |
| } | |
| havePendingRefresh = true | |
| pendingRefreshScreenIsDefinitelyUnlocked = screenIsDefinitelyUnlocked | |
| pendingRefreshScreenIsDefinitelyUnlocked = screenIsDefinitelyUnlocked | |
| if havePendingRefresh { return } | |
| havePendingRefresh = true |
This way we will run the next refresh session with the latest known screenIsDefinitelyUnlocked
wdyt?
Collaborator
Author
There was a problem hiding this comment.
My logic for preferring true here was that the comments at
AeroSpace/Sources/AppBundle/tree/frozen/closedWindowsCache.swift
Lines 111 to 124 in ae0e577
Owner
There was a problem hiding this comment.
Thanks, makes sense.
Merged with the following cleanup patch:
diff --git a/Sources/AppBundle/initAppBundle.swift b/Sources/AppBundle/initAppBundle.swift
index 38751b79..c64d0fc8 100644
--- a/Sources/AppBundle/initAppBundle.swift
+++ b/Sources/AppBundle/initAppBundle.swift
@@ -23,7 +23,7 @@ import Foundation
AXUIElementSetMessagingTimeout(AXUIElementCreateSystemWide(), 1.0)
startUnixSocketServer()
GlobalObserver.initObserver()
- refreshAndLayout(.startup1, screenIsDefinitelyUnlocked: false, startup: true)
+ refreshSession(.startup1, screenIsDefinitelyUnlocked: false, startup: true, body: {})
refreshSession(.startup2, screenIsDefinitelyUnlocked: false) {
if serverArgs.startedAtLogin {
_ = config.afterLoginCommand.runCmdSeq(.defaultEnv, .emptyStdin)
diff --git a/Sources/AppBundle/layout/refresh.swift b/Sources/AppBundle/layout/refresh.swift
index 8ac24370..91cafb31 100644
--- a/Sources/AppBundle/layout/refresh.swift
+++ b/Sources/AppBundle/layout/refresh.swift
@@ -42,27 +42,16 @@ func refreshSession<T>(_ event: RefreshSessionEvent, screenIsDefinitelyUnlocked:
return result
}
-@MainActor
-func refreshAndLayout(_ event: RefreshSessionEvent, screenIsDefinitelyUnlocked: Bool, startup: Bool = false) {
- refreshSession(event, screenIsDefinitelyUnlocked: screenIsDefinitelyUnlocked, startup: startup, body: {})
-}
-
@MainActor private var havePendingRefresh = false
-@MainActor private var pendingRefreshScreenIsDefinitelyUnlocked = false
@MainActor
func scheduleRefreshAndLayout(_ event: RefreshSessionEvent, screenIsDefinitelyUnlocked: Bool = false) {
- if havePendingRefresh {
- if screenIsDefinitelyUnlocked {
- pendingRefreshScreenIsDefinitelyUnlocked = true
- }
- return
- }
+ if screenIsDefinitelyUnlocked { resetClosedWindowsCache() }
+ if havePendingRefresh { return }
havePendingRefresh = true
- pendingRefreshScreenIsDefinitelyUnlocked = screenIsDefinitelyUnlocked
DispatchQueue.main.async { @MainActor in
havePendingRefresh = false
- refreshSession(event, screenIsDefinitelyUnlocked: pendingRefreshScreenIsDefinitelyUnlocked, startup: false, body: {})
+ refreshSession(event, screenIsDefinitelyUnlocked: false, startup: false, body: {})
}
}
ZimengXiong
pushed a commit
to ZimengXiong/winmux
that referenced
this pull request
Apr 6, 2026
On operations like workspace changes, AeroSpace receives a stampede of accessibility events, each of which triggers a serial call to `refreshSession()` on the main thread. Since these `refreshSession()` calls are idempotent, we can coalesce these calls so that multiple accessibility events can be handled by a single `refreshSession()`. With this change, operations like workspace switch go from O(num_source_windows + num_dest_windows) to O(1) `refreshSession()` calls (with similar improvements for operations like closing windows or resizing windows). closes nikitabobko/AeroSpace#1249 related: nikitabobko/AeroSpace#131
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On operations like workspace changes, AeroSpace receives a stampede of
accessibility events, each of which triggers a serial call to
refreshSession()on the main thread. Since theserefreshSession()callsare idempotent, we can coalesce these calls so that
multiple accessibility events can be handled by a single
refreshSession().With this change, operations like workspace switch go from
O(num_source_windows + num_dest_windows) to O(1)
refreshSession()calls (with similar improvements for operations like closing windows or
resizing windows).