perf: suppress redundant icon observer callbacks#1081
Merged
Conversation
Remove isRefreshing from iconObservationToken and add observer-side signature guard to skip updateIcons() when icon-relevant state is unchanged. The existing render signature inside applyIcon() avoided redundant icon rendering, but not redundant observer work. This change reduces observer callback churn before render-signature checking is reached. Before: updateIcons() called 10 times per refresh cycle (1 rendered) After: updateIcons() called 6 times per refresh cycle (1 rendered) Split from steipete#1073. Related: steipete#678.
274c47c to
c942861
Compare
steipete
approved these changes
May 21, 2026
Owner
steipete
left a comment
There was a problem hiding this comment.
Reviewed the icon observer suppression path, ran focused tests, lint/check, Codex autoreview, and a release bundle relaunch smoke. Added the maintainer changelog entry and rebased onto current main.
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.
Summary
Narrow the icon observation path so
updateIcons()only fires when icon-relevant state changes.The existing render signature inside
applyIcon()already avoided redundant icon rendering, but it did not prevent redundant observer work from reachingupdateIcons(). This change reduces observer callback andupdateIcons()churn before render-signature checking is reached.Split from #1073 per review feedback. Related: #678.
Not included
Problem
StatusItemController.observeStoreIconChanges()watchesUsageStore.iconObservationToken, which registers Swift Observation dependencies on multiple store fields.isRefreshingtoggles on every refresh cycle regardless of icon state. That causes the observer to re-fire and callupdateIcons()even when no icon-relevant state changed.That does not necessarily mean every observer fire performs an expensive render:
applyIcon()already has render-signature checks and often skips unchanged icon rendering. The issue fixed here is narrower: unnecessary observer/updateIcons work was still happening before those render-signature checks were reached.Changes
isRefreshingfromiconObservationTokenbecause refresh start/finish state is not itself icon-relevant.storeIconObservationSignature()to derive a signature from actual icon-relevant state.updateIcons()when the derived store icon signature is unchanged.[perf]instrumentation gated behinddebugLogLevel=verbosefor future diagnosis.Measurement
Measured with
[perf]instrumentation gated bydebugLogLevel=verbose.Scope: startup refresh cycles only.
main)updateIcons()calls per refresh cycleapplyIcon()render-signature skips per refresh cycleScope note
This PR does not claim to fully explain or fix the original 99% CPU spike from #1073. After local account pruning from 7 managed Codex accounts to 3 kept/paid accounts, I can no longer reproduce the sustained CPU peg on demand.
The scoped claim here is narrower: refresh-state churn was causing
observeStoreIconChanges()to callupdateIcons()even when the icon-relevant store signature had not changed. This PR removes that redundant observer work before render-signature checks are reached.Testing
StatusItemIconObservationSignatureTestsisRefreshingchurnswiftformatswiftlint --strictmake check