-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
It was reported here PowerShell/PowerShell-RFC#194 by @Ayanmullick
that
The below script runs faster without -parallel than with.
(Get-WinEvent -ListLog * -EA SilentlyContinue).Where({$PSItem.recordcount -ne '0'}).Logname|
ForEach-Object -Parallel {Get-WinEvent -FilterHashtable @{logname = "$PSItem";Starttime ='8/24/2019 11:00:00';Endtime ='8/24/2019 11:09:00';Level=1,2,3} -EA SilentlyContinue }
It took 18 secs to finish with -parallel and only 5 without.
Thomas Lee put up this case where it was slower. https://twitter.com/doctordns/status/1164461929093566465
It is understood that parallelizing trivial code in will more overhead than the time saved
Using Start-Parallel from the PowerShell Gallery I ran this to ping every machine on my local subnet. 200 addresses are not used, so in sequence it would take 800-1000 seconds.
1..254 | Start-Parallel -Scriptblock {param ($P) ping "192.168.0.$p" -n 1 | where {$_ -match "ttl="}} -MaxThreads 300
it took 9 seconds
The new equivalent is
1..254 | foreach -Parallel {ping "192.168.0.$_" -n 1 | where {$_ -match "ttl="}} -ThrottleLimit 300
Which takes 31 seconds; I would expect broadly similar performance with the cmdlet slightly faster.
Using threadjob which ships with PS 6 and 7 I created this
$j = 1..254 | foreach {
$sb=[scriptblock]::Create("ping -n 1 192.168.0.$_ | where {`$_ -match 'TTL=' } ")
Start-ThreadJob -ScriptBlock $sb -ThrottleLimit 300 }
while ($j.state -eq "running" -or $j.hasmoredata -eq $true) {
foreach ($finished in $j.where({$_.state -eq "completed"})){ receive-job -Id $finished.id; } }
Which runs in 11 seconds.
The cmdlet should be doing something very similar to this but not taking 3 times as long