Skip to content

CmdPal: Avoid all-stripe locking in the adaptive icon cache - #49737

Merged
Mike Griese (zadjii-msft) merged 2 commits into
mainfrom
dev/jpolasek/f/cmdpal-adaptive-cache-reentrancy
Aug 7, 2026
Merged

CmdPal: Avoid all-stripe locking in the adaptive icon cache#49737
Mike Griese (zadjii-msft) merged 2 commits into
mainfrom
dev/jpolasek/f/cmdpal-adaptive-cache-reentrancy

Conversation

@jiripolasek

@jiripolasek Jiří Polášek (jiripolasek) commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Summary of the Pull Request

This PR removes all-stripe synchronization from AdaptiveCache. Using ConcurrentDictionary.Count for capacity checks and Keys while clearing could acquire every dictionary stripe, allowing XAML-bound icon cache operations to wait behind unrelated concurrent mutations.

The main problem here is that WinUI doens't take locked main STA thread well and can fail-fast the app.

  • Track an approximate entry count with atomic updates after successful mutations.
  • Use the approximate count for capacity checks and maintenance decisions.
  • Enumerate the dictionary directly when clearing instead of snapshotting Keys.
  • Add concurrent cleanup and count-consistency regression tests.
  • Add a matching CmdPal UI unit-test project to the solution.

PR Checklist

  • Closes: #xxx
  • Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
  • Tests: Added/updated and all pass
  • Localization: All end-user-facing strings can be localized
  • Dev docs: Added/updated
  • New binaries: Added on the required places
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

Validation Steps Performed

ConcurrentDictionary.Count and .Keys acquire all stripe locks, so cache maintenance could block the STA XAML thread and lead to WinUI fail-fast crash.

- Replaces ConcurrentDictionary.Count checks with the approximate entry count.
- Tracks cache entries atomically after successful additions and removals.
- Enumerates the dictionary in Clear instead of snapshotting Keys.
- Adds unit tests.

@zadjii-msft Mike Griese (zadjii-msft) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems reasonable

Comment thread PowerToys.slnx
@zadjii-msft
Mike Griese (zadjii-msft) merged commit 6014605 into main Aug 7, 2026
8 checks passed
@zadjii-msft
Mike Griese (zadjii-msft) deleted the dev/jpolasek/f/cmdpal-adaptive-cache-reentrancy branch August 7, 2026 17:40
Michael Jolley (michaeljolley) added a commit that referenced this pull request Aug 7, 2026
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This PR is stacked on #49737 and separates in-flight icon loading from
completed-result caching. The XAML request path no longer takes a
provider-wide lock, while concurrent requests for the same icon still
share a single task and completion cleanup can retire only that exact
task generation.

The loader now reports whether queue admission succeeded, preventing
requests rejected during shutdown from remaining pending indefinitely.

Overall, it seems that we got rid of a lock and actually reduced
turnaround on UI thread. The separate in-flight tracking takes its tall,
but overall throughput increased (tl;dr - it's faster).

- Deduplicate outstanding icon loads in a dedicated in-flight
dictionary.
- Cache successful tasks before atomically retiring their in-flight
entries.
- Keep failed and rejected loads out of the adaptive cache so they can
be retried.
- Replace `EnqueueLoad` with `TryEnqueueLoad` and fault rejected
requests.
- Add tests for concurrent loading, publication ordering, failures,
rejection, and retries.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

0.101 Product-Command Palette Refers to the Command Palette utility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants