Skip to content

Run test files in parallel on Windows PowerShell 5.1 too - #2987

Merged
nohwnd merged 3 commits into
mainfrom
parallel-on-windows-powershell
Aug 22, 2026
Merged

Run test files in parallel on Windows PowerShell 5.1 too#2987
nohwnd merged 3 commits into
mainfrom
parallel-on-windows-powershell

Conversation

@nohwnd

@nohwnd nohwnd commented Aug 22, 2026

Copy link
Copy Markdown
Member

Run.Parallel was built on ForEach-Object -Parallel, which only exists on PowerShell 7, so Windows PowerShell 5.1 warned and ran sequentially. 5.1 is the slowest leg in our matrix and it decides how long a build takes (#2985), so it is the edition that needs this most.

Both editions now go through Invoke-InRunspacePool, a pool built on the runspace API that 5.1 and 7 both have. No new dependency, about 90 lines in Pester.Parallel.ps1.

Three things ForEach-Object -Parallel did that the pool does not:

  • $using: is its feature, not the runspace API's, so the worker takes named parameters instead. Same process either way, so the values still cross as live objects.
  • The worker scriptblock goes over as text and is re-parsed in the runspace, so nothing with runspace affinity crosses.
  • A pooled runspace starts at the process working directory, not the caller's location. ForEach-Object -Parallel keeps the location and test files resolve relative paths against it, so the worker sets it from the parent.

Passing the values as arguments instead of capturing them with $using: is a tip @DarkLite1 gave in #2971. Thanks.

The parallel tests no longer skip their assertions on 5.1, they run the same ones as on 7 including the console output snapshot. Added tests for the pool itself: concurrency, throttle, parameter passing, a worker throwing, empty input.

🤖

nohwnd added 3 commits August 22, 2026 09:56
Run.Parallel was built on ForEach-Object -Parallel, which only exists on
PowerShell 7, so on Windows PowerShell 5.1 it warned and ran sequentially. 5.1 is
the slowest leg in our own matrix and it is the one that sets how long a build
takes, so it is the edition that needs this most.

Both editions now go through Invoke-InRunspacePool, a runspace pool built on the
API that 5.1 and 7 both have. One code path, so the two editions cannot drift.
The worker scriptblock takes its values as named parameters instead of $using:,
which is a ForEach-Object -Parallel feature, and it is handed over as text and
re-parsed in the worker so nothing with runspace affinity crosses. The runspaces
are in this process either way, so the values still cross as live objects.

A pooled runspace starts at the process working directory rather than the
caller's location, which ForEach-Object -Parallel preserves, so the worker sets
it from the parent.

The tests that were asserting parallel behaviour only on 7+ now run on both, so
5.1 is covered by the same assertions and not by a fallback message. Added tests
for the pool itself: concurrency, throttle, parameter passing, one worker
throwing without taking the rest down, and empty input.

No new dependency, the implementation is in the module.

🤖
The throttle test slept 4 x 500ms through one runspace and asserted the run took
at least 2000ms. Start-Sleep can come back a hair early, so the total lands just
under the threshold and the test fails for a reason that has nothing to do with
the pool. It did exactly that on the PS7 Windows 2022 leg.

Each worker now counts itself in and out of a synchronized hashtable, so the peak
number in flight is measured rather than inferred from a clock. One runspace can
only ever peak at 1, which is exact, and the concurrent case asserts more than
one in flight without pinning the peak to a number the scheduler decides.

🤖
It reads like a way to turn parallel off, and it is not. The files still go
through the parallel machinery, one at a time in their own runspace, so the
isolation stays and a breakpoint set in the calling session still does not hit
inside a worker.

🤖
@nohwnd
nohwnd merged commit f765140 into main Aug 22, 2026
20 checks passed
@nohwnd
nohwnd deleted the parallel-on-windows-powershell branch August 22, 2026 11:03
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.

1 participant