Repository navigation
Reduce PowerShell module build analysis and formatting overhead - #1024
Merged
Merged
Conversation
This was referenced Oct 4, 2026
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.
PowerShell module builds repeatedly bind the same commands during analysis and reload PowerShell/PSScriptAnalyzer across formatting groups and phases. Cache successful bindings within an analysis, restrict execution-graph candidates to their actual function scope, skip disabled preprocessing, and batch each tree's file groups. The build now owns one isolated formatter host across staging and project formatting, then disposes it before later actions and signing.
Each group and phase retains its settings, working directory, deadline, and per-file results. Completed errors remain errors when a later file times out; the interrupted host is discarded before another request. A staging failure stops project formatting. Normalization writes only when target bytes differ, reports encoding-only changes correctly, and preserves timestamps for already-normalized files. The implementation stays in PowerForge and PowerForge.PowerShell, with no public API or production dependency changes.
Related consumers are Locksmith #299 and Locksmith2 #111. Their public minimum remains 3.0.153. Publish a PSGallery version containing the owner changes before raising that minimum.
Validation includes 38 focused formatter/normalization contracts, including six child-process lifecycle cases; zero-warning builds for net472/net8.0/net10.0; real PSScriptAnalyzer output equivalence with different settings, Unicode, and casing on PowerShell 7.6.6 and Windows PowerShell 5.1; and real Build-Module staging-failure checks on both hosts. Independent local review covers the analysis/batching, normalization, and added host-lifetime contracts with no unresolved findings. Earlier broader module validation and the packed 3.0 script path have separate proof; broad unfiltered engine validation is not claimed complete.
The latest full comparison uses 2.0.27, the preceding implementation at 2dc7cd2, and the formatter-reuse production files committed at 8e901ef. Both cache domains use fixed affinity, normal priority, one warm-up and three rotated measured builds per engine/module, identical cached dependencies, project formatting enabled, and no outlier removal.
Whole-build results are mixed: Locksmith2 improves about 18% on the second domain, while its first-domain median worsens. Ranges remain wide; the first domain contains approximately 118-second samples in both the legacy and reused lanes. A nearby snapshot shows a shared Roslyn compiler consuming roughly 16 CPU-core equivalents, which limits attribution. No formatter timeout appears in these build logs. This comparison does not establish a consistent whole-build improvement or a win over 2.0.
Separate phase diagnostics show project formatting falling from 0.702 to 0.055 seconds for Locksmith and 1.911 to 0.180 seconds for Locksmith2. These are individual diagnostic runs, not benchmark medians; staging formatting remains the dominant cost.
All 36 measured artifacts pass structural checks. The before/reused 3.0 artifacts import on both runtimes with 1 and 9 exports, and all five compared output files are byte-identical on each domain. Legacy Locksmith imports on Desktop; its Core import is blocked by the older ServerManager manifest requirement on this workstation. Locksmith uses Script-only for all engines because the tested 2.0 packed path does not produce a valid ZIP. Runs 20261004-174939-d518ff89 and 20261004-181423-03e6d6a7 retain every measured sample; incomplete dependency-cache attempts are excluded.
Native private packages 3.0.155.6/3.0.155.7 are validation artifacts only. The candidate package was built before committing its reviewed production files, so its embedded Git metadata may retain the preceding SHA; native DLL fingerprints are retained. This PR is separate from package publication and consumer release qualification.