fix(perf): pre-warm software-list icons off-main (Sentry BURROW-20)#87
Merged
Conversation
The uninstall/software list rendered each AppRow by calling SoftwareIcons.icon()/version() in the row body on the main thread: NSWorkspace.icon(forFile:) hits the app bundle and version() reads Info.plist, so the first paint of a large /Applications list did O(rows) disk reads on the main thread during layout — an App Hang (Sentry BURROW-20, top frame "InstalledApp"). - SoftwareIcons is now NSLock-guarded and resolves icons + versions on a utility queue; icon()/version() are main-safe cache reads that return a placeholder/nil and fill asynchronously on a miss. - fetch() pre-warms the cache off-main (it always runs on a background queue), so rows render from a pure cache read. - InstalledApp is Equatable so unchanged rows diff cheaply. Mirrors the off-main app-icon resolution for the process table in #83.
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.
What
BURROW-20("App Hanging" / top frameInstalledApp) — the Uninstall/Software list stalls the main thread on first paint of a large app list.Root cause
AppRowrenders each row by callingSoftwareIcons.icon(app.path)andSoftwareIcons.version(app.path)in the row body, on the main thread:icon()→NSWorkspace.shared.icon(forFile:)reads the app bundleversion()reads each bundle'sContents/Info.plistThe cache filled on first access, so the first paint of a full
/Applicationslist did O(rows) disk reads on the main thread during layout → an App Hang. Same class as the process-table app-icon walk fixed in #83, but a different surface that PR didn't cover.Fix
SoftwareIconsis nowNSLock-guarded and resolves icons + versions on a.utilityqueue.icon()/version()are main-safe cache reads — a hit returns immediately; a miss returns a generic placeholder /niland schedules an off-main fill (the row picks it up on the next redraw).fetch()pre-warms the cache off-main (it always runs on a background queue), so rows render from pure cache reads — no disk on main during layout.InstalledApp: Equatableso unchanged rows diff cheaply.Verification
xcodebuild … build→ BUILD SUCCEEDED, no new warnings.Notes
Kept separate from #83 (process table / clean reports) to keep each PR focused. Don't auto-resolve BURROW-20 in Sentry until a release carrying this has soaked — the top hangs regressed after a premature resolve last time.