Skip unused work in discovery post-processing and output#2918
Open
nohwnd wants to merge 1 commit into
Open
Conversation
The WriteScreen plugin flattened the whole discovered tree with View-Flat on DiscoveryEnd, but the result is only read when Run.SkipRun is set or verbosity is Detailed/Diagnostic, in the default run it was computed and thrown away. It is now computed only when one of those consumers can read it. The RSpec decoration walk (Add-RSpecTestObjectProperties per test) and Remove-RSpecNonPublicProperties used Fold-Container/Fold-Run, which pay a scriptblock dispatch per item and an advanced-function recursion per block. Both are now direct recursive loops that visit the same items in the same pre-order. Format-Nicely2 called Is-DecimalNumber, Is-ScriptBlock, Is-Collection and Is-Value helpers on every formatted value, on the dispatch path used for every <template> name expansion. The type checks are inlined, the helpers stay defined for other callers. 🤖
This was referenced Jul 19, 2026
fflaten
reviewed
Jul 19, 2026
Collaborator
There was a problem hiding this comment.
Just curious so I can learn, what's the big benefit here besides clearer names? We skip maybe 1-2 light function calls, but all the scriptblocks are reference types and passed on from the initial call.
| if (Is-DecimalNumber -Value $Value) { | ||
| # Inlined Is-DecimalNumber / Is-ScriptBlock to avoid a function call per formatted value on this | ||
| # hot dispatch path (used for every <template> name expansion). The helpers stay defined for other callers. | ||
| if ($Value -is [float] -or $Value -is [single] -or $Value -is [double] -or $Value -is [decimal]) { |
Collaborator
There was a problem hiding this comment.
Is-DecimalNumber is only used here and Format.ps1. Maybe update both?
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.
Three changes on the discovery and post-processing side:
View-FlatonDiscoveryEnd, but the result is only read whenRun.SkipRunis set or verbosity isDetailed/Diagnostic. In the default run it was computed and thrown away, the cost grows with the number of discovered tests. It is now computed only when one of those two guarded blocks can actually read it.Add-RSpecTestObjectPropertiesper test, run once per container after it finishes) andRemove-RSpecNonPublicPropertiesusedFold-Container/Fold-Run, which pay a scriptblock dispatch per item plus an advanced-function recursion per block. Both are now direct recursive loops that visit the same items in the same pre-order (tests of a block before its child blocks). The decoration body itself is unchanged and stays in one place, the walker just calls it.Format-Nicely2called theIs-DecimalNumber,Is-ScriptBlock,Is-CollectionandIs-Valuehelpers on every formatted value, and it runs for every<template>name expansion of data-driven tests. The type checks are inlined (Is-Collectionis the sameLanguagePrimitives::GetEnumeratortest), the helpers stay defined for their other callers.Verification: full suite green on macOS (inline and dot-sourced build),
Pester.RSpec.ts.ps1,Pester.RSpec.Parallel.ts.ps1(covers the parallel decoration path, which changed too) andPester.RSpec.Output.ts.ps1pass in fresh processes. Result object shape is covered byPester.RSpec.ResultObject.ts.ps1, also green.Related perf PRs: #2914, #2915, #2916, #2917. Measured together they cut ~21% from four representative workloads (inline build, macOS).
🤖