Skip to content

Reduce allocations for cached command lookups - #2221

Closed
Przemysław Kłys (PrzemyslawKlys) wants to merge 1 commit into
PowerShell:mainfrom
PrzemyslawKlys:fix/formatter-performance
Closed

Przemysław Kłys (PrzemyslawKlys) wants to merge 1 commit into
PowerShell:mainfrom
PrzemyslawKlys:fix/formatter-performance

Conversation

@PrzemyslawKlys

Copy link
Copy Markdown
Contributor

PR Summary

Repeated command lookups allocate a closure, a Lazy<CommandInfo>, and an uppercased key even when the result is already cached. Return the existing lazy value first, move miss-only allocations into a helper, and use StringComparer.OrdinalIgnoreCase for hashing to match key equality.

Command discovery, command-type filters, bypass behavior, and the winning lazy value on concurrent misses are unchanged. Tests cover cached identity across casing and equivalent command types, separate type filters, and culture-independent lookup.

With command names extracted from Locksmith and Locksmith2, cached-lookup medians fall by 55–61% across two CPU cache domains (two warmups and seven rotated samples per lane). The measured C# lookup loop allocates zero bytes after the change, versus 203 MB / 333 MB before it for 890,000 / 1,400,000 lookups. These are cached-lookup results, not whole-formatting or build speedups. Baseline: 411c3d0b197b488285bddd2375b292ab7b8db5e8.

Validation: net8 and net462 builds; 41 focused tests pass with one skipped on each PowerShell Core and Windows PowerShell. Full formatting of both modules produces identical bytes and diagnostics before/after on each runtime. Locksmith2 retains an existing attribute-construction diagnostic in this isolated test.

Related performance discussion: #1528.

PR Checklist

  • PR has a meaningful title
  • Summarized changes
  • Change is not breaking
  • C#, PowerShell script and module files have the correct copyright header
  • Added tests for the changed contracts
  • This PR is ready for review and is not Work in Progress

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The focused optimization preserves existing semantics and is adequately covered by targeted tests.

Review effort: Balanced
Findings: None

What changed in this PR

Optimizes cached command lookups while preserving lookup behavior and thread safety.

Changes:

  • Avoids miss-only allocations on cache hits.
  • Uses ordinal case-insensitive hashing.
  • Adds cache identity, filtering, and culture tests.
File Description
Engine/​CommandInfoCache.cs Adds allocation-free cache-hit path and matching hash semantics.
Tests/​Engine/​CommandInfoCache.tests.ps1 Tests casing, command types, and culture independence.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@jessehouwing

Copy link
Copy Markdown

Fixed in #2206 with more significant improvements.

Verdict: PR #2221’s implementation is already covered in #2206. The two substantive optimizations are present:

  • CommandInfoCache.cs:121-149 checks the cache before creating the Lazy factory. Cached hits therefore avoid the closure and Lazy allocations; concurrent misses still share the winning entry.
  • CommandLookupKey.cs:24-37 keeps the original name and hashes with StringComparer.OrdinalIgnoreCase, avoiding the uppercase-string allocation while matching the key’s equality comparison.

Jesse Houwing (jessehouwing) added a commit to jessehouwing/PSScriptAnalyzer that referenced this pull request Oct 7, 2026
…d command-type filtering

Adding additional test cases from PowerShell#2221.
@PrzemyslawKlys

Copy link
Copy Markdown
Contributor Author

Thanks for pointing this out. I checked #2206 and confirmed that it already includes both the cache-hit allocation change and ordinal case-insensitive hashing. Closing this PR as superseded by #2206.

@jessehouwing

Copy link
Copy Markdown

I did steal your additional tests! Thanks! Would be helpful if you can run the code from that PR and report your findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants