If a script needs some speed-up, you might find background jobs helpful. They can be used if a script does a number of things that also could run concurrently.
PowerShell is single-threaded and can only do one thing at a time. With background jobs, additional PowerShell processes run in the background and can share the workload. This works well only if the jobs you need to do are completely independent from each other, and if your background job does not need to produce a lot of data. Sending back data from a background job is an expensive procedure that can easily eat up all the saved time, resulting in an even slower script.
Here are three tasks that all can run concurrently: | $start = Get-Date | | | | | | $task1 = { Get-Hotfix } | | | | | | $task2 = { Get-Service | Where-Object Status -eq Running } | | | | | | $task3 = { Get-Content -Path $env:windir\windowsupdate.log | Where-Object { $_ -like '*successfully installed*' } } | | | | | | $job1 = Start-Job -ScriptBlock $task1 | | $job2 = Start-Job -ScriptBlock $task2 | | $result3 = Invoke-Command -ScriptBlock $task3 | | | | | | $null = Wait-Job -Job $job1, $job2 | | | | | | $result1 = Receive-Job -Job $job1 | | $result2 = Receive-Job -Job $job2 | | | | | | Remove-Job -Job $job1, $job2 | | | | $end = Get-Date | | Write-Host -ForegroundColor Red ($end - $start).TotalSecondsCOPY |
On a sample system, executing all three tasks took 5.9 seconds. The results for all three tasks are available in $result1, $result2, and $result3.
Let's check how long it takes for all three tasks to run consecutively in the foreground. | $start = Get-Date | | | | | | $task1 = { Get-Hotfix } | | | | | | $task2 = { Get-Service | Where-Object Status -eq Running } | | | | | | $task3 = { Get-Content -Path $env:windir\windowsupdate.log | Where-Object { $_ -like '*successfully installed*' } } | | | | | | $result1 = Invoke-Command -ScriptBlock $task1 | | $result2 = Invoke-Command -ScriptBlock $task2 | | $result3 = Invoke-Command -ScriptBlock $task3 | | | | $end = Get-Date | | Write-Host -ForegroundColor Red ($end - $start).TotalSecondsCOPY |
As it turns out, this time it only took 5.05 seconds. So background jobs really pay off for long running tasks that all take almost the same time. Since the three sample tasks returned a lot of data, the benefit of executing them concurrently was eliminated by the overhead that it took to serialize the return data and transport it back to the foreground process.
http://powershell.com/cs/blogs/tips/archive/2014/04/11/parallel-processing-in-powershell.aspx |