Reputation: 11966
When I execute a simple statement locally
$path = 'C:\Windows\System32\WindowsPowerShell\v1.0'
gci $path
I see the response immediately. But when I execute it as job on my local machine
$start = get-date
$path = 'C:\Windows\System32\WindowsPowerShell\v1.0'
$cmd = [scriptblock]::Create("gci $path")
$jnr1 = Invoke-Command -computer localhost -ScriptBlock $cmd -asJob
Wait-Job $jnr1
Receive-job $jnr1
$end = Get-date
($end - $start).totalseconds
I have to wait 55 seconds. From my unix experience a decade ago. I would expect background jobs to run nearly as fast as foreground jobs.
Are there ways to speed up the execution of PowerShell background jobs?
Upvotes: 7
Views: 8521
Reputation: 302
Your demo works quite fast on a windows server I tested. I believe in this particular case it might not be problem with jobs, but rather with calling the localhost! Try changing it to 127.0.0.1 instead. I had a problem with performance of PHP app because it somehow took too long to resolve localhost. Changing it to ip address fixed it. Give it a try.
related discussion https://forums.iis.net/t/1153459.aspx?PHP+very+slow+on+IIS7
Upvotes: 0
Reputation: 1082
I'm having a problem with slow jobs too where it runs fast in the foreground, but your problem is so pronounced for a single command that I'd suspect it's something related to the cost or some machine specific difficulty of spawning a new powershell process. (Yes, you get an extra powershell.exe for every concurrent job.) For a lot of people though, it's more than that. This post: (https://vwiki.co.uk/Background_Jobs_(PowerShell)) mentions that jobs are run in PS as below normal priority by default. Some posts suggested putting one of the following in the job code block to fix mostly CPU problems:
[System.Threading.Thread]::CurrentThread.Priority = 'AboveNormal'
([System.Diagnostics.Process]::GetCurrentProcess()).PriorityClass = 'AboveNormal'
Unfortunately for me, I think I'm having an I/O performance problem as upposed to a CPU performance problem with jobs. This post: (How to set Low I/O ("background") priority in Powershell) touches on the concept of increasing memory and IO priority, but I didn't see an answer that I feel comfortable implementing.
One of the most important features of Powershell jobs is parallel execution of multiple jobs. An alternative to PS Jobs are PS "Workflows", but it seems I still have the same performance problems with workflows as with jobs. Very frustrating.
Upvotes: 0
Reputation: 52609
This shorter command does the same thing:
Measure-Command {Start-Job -Command {gci C:\Windows\System32\WindowsPowerShell\v1.0} | Wait-Job | Receive-Job}
On Win8 beta w/ PSv3 it was fast for me ~3 seconds, on WinXp w/ PSv2 it was ~15-30 seconds.
Background jobs were introduced w/ PsV2. They've had time to optimize since v2 and PowerShell now uses the DLR in v3 now so that might explain the differences in performance.
It has to spin up another powershell process with the command text, run the command, send back the serialized results and tear down the process.
To find out what its doing I ran procmon while the above command was running and a majority of the time powershell.exe was reading networking and COM related reg keys.
Upvotes: 4