Fix multi-second first-click delay after boot (startup optimizations, v0.3.0.0)#67
Open
martinperreault wants to merge 3 commits into
Open
Fix multi-second first-click delay after boot (startup optimizations, v0.3.0.0)#67martinperreault wants to merge 3 commits into
martinperreault wants to merge 3 commits into
Conversation
… v0.3.0.0) The first click on a pinned group after a reboot had to cold-start the tray-resident background host (~5s); every later click was instant. This release attacks that cold start on four fronts: - Fix Multicore JIT in the background client: SetProfileRoot was only ever called in the editor, making the existing StartProfile call a silent no-op on the hot path. Also profile the startup path itself. - Lazy group loading: startup now only indexes group folders; XML deserialization + icon decoding happen on demand at click time, with all groups pre-warmed on a background thread after tray init. - Defer jump-list construction (WindowsAPICodePack + shell COM) until after the popup is shown; the setGroupContextMenu registration path is preserved. - New "Start at login (instant first click)" toggle in the editor (default on, HKCU Run key, disabled in portable mode): the host is already resident before the first click, hiding any remaining cold start entirely. Launching the exe with no args already starts it resident, so no new argument was needed. Also fixes portable-mode toggle writing portableMode=true even when disabling (previously self-corrected only on next launch). Docs: OPTIMIZATION_PLAN.md (final plan), PLAN_REVIEW.md (independent verification), CHANGELOG.md, build.ps1 (reproducible Release build). Existing groups, pins, AppUserModelIDs, config layout, and the pinned .lnk command-line contract are unchanged; upgrading is running the new editor once (existing MD5 self-update mechanism). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
closeBackgroundApp launched a messenger copy of the background exe to deliver the exit signal but only waited on the resident process; the messenger also holds a lock on the same exe file, so the immediate WriteAllBytes in setupBackgroundApplication raced it and threw an unhandled IOException from inside the Paths static initializer, killing the editor mid-upgrade (found live during the v0.3.0.0 rollout; a resident host is the normal case now that launch-at-login exists). - closeBackgroundApp: wait on the messenger process and on every remaining instance, including after Kill() (which is async). - setupBackgroundApplication: retry the exe write briefly on IOException; on persistent failure keep the previous helper and inform the user instead of crashing (mismatch retries next launch). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Condensed record of the investigation: root causes with proof, the cost-attribution correction, the latent upgrade-race bug found during rollout, verification performed, and the compatibility invariants any future change must preserve. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
Fixes the multi-second delay on the first click of a pinned taskbar group after a reboot (subsequent clicks were always instant). Root cause: that first click has to cold-start the tray-resident single-instance background host; everything after just messages the warm instance.
Four fixes attack the cold start (full analysis in
FINDINGS.md, plan + verification inOPTIMIZATION_PLAN.md/PLAN_REVIEW.md):ProfileOptimization.StartProfilewas already called infrmMain, butSetProfileRootonly ever ran in the editor, making it a silent no-op for the background client. Now set inProgram.Main, with a startup profile added. (Easy to confirm on any install:%LocalAppData%\Jack Schierbeck\taskbar-groups\JITComp\never contained background-client profiles before this change.)setGroupContextMenuregistration path is preserved.Runkey, disabled in portable mode, applied immediately). Launching the background exe with no arguments already starts it tray-resident without a popup, so this needed no new hot-path code. This is the decisive fix: the host is resident before the user's first click.Bug fixes
closeBackgroundAppspawns a messenger copy of the background exe to deliver the exit signal but only waited on the resident process — the messenger also locks the exe file, andProcess.Kill()is async, so the immediateFile.WriteAllBytesinPaths.setupBackgroundApplicationraced the lock and threw an unhandledIOExceptionfrom the static initializer. Now waits on all instances and retries the write; on persistent failure it keeps the previous helper and informs the user instead of crashing. With launch-at-login, a resident host during upgrades is the normal case.portableMode=trueeven when disabling portable mode (previously self-corrected only on next launch).Compatibility
Existing groups, pinned shortcuts, AppUserModelIDs, config layout,
Settings.xmlschema (new element is optional with a default), and the pinned-.lnkargument contract are unchanged. Upgrading is: run the new editor once (existing MD5 self-update mechanism replaces the background exe).Build
build.ps1added: reproducible Release build (offline NuGet layout restore from the checked-inlib\DLLs, COM interop generation, correct build order — background client before editor, since the editor embeds it). Version bumped to 0.3.0.0.Testing
<GroupName>arg → popup via single-instance handoff;exitApplicationModeReserved→ clean exit; JIT profiles now written.🤖 Generated with Claude Code