views:

206

answers:

3

Hi,

I'm running a number of scripts using PowerShell V2, and I have noticed a long pause when the console window first loads. What can I do to improve the performance of my scripts?

Thanks, MagicAndi

+5  A: 

Other than minimize what you put in your various profile scripts (shown below) there isn't much you can do:

C:\PS> $profile | fl * -force


AllUsersAllHosts       : C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
AllUsersCurrentHost    : C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1
CurrentUserAllHosts    : C:\Users\hillr\Documents\WindowsPowerShell\profile.ps1
CurrentUserCurrentHost : C:\Users\hillr\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

One way to check to see if profile scripts are causing the lag is to start powershell using the -noprofile option. If the startup time is different it would be due to your profile scripts. You can use a .NET stopwatch like so:

function TimeThis([scriptblock]$scriptblock, $msg)
{
    if (!$stopWatch)
    {
        $script:stopWatch = new-object System.Diagnostics.StopWatch
    }
    $stopWatch.Reset()
    $stopWatch.Start()
    . $scriptblock
    $stopWatch.Stop()
    if ($msg -eq $null) { $msg = "$scriptblock" }
    "Execution time: $($stopWatch.ElapsedMilliseconds) mS for $msg"
}

. TimeThis {Import-Module $Module -args ~\Pscx.UserPreferences.ps1}

While you could use Measure-Command, it doesn't show what is executed and you get no command output (only time in a very verbose fashion).

There used to be an issue in earlier CTPs where the installer wouldn't ngen the PowerShell assemblies and that could cause noticeable load time delays. However I'm pretty sure that has been fixed as of the final 2.0 install (and certainly with PowerShell built into Windows 7 and Windows Server 2008 R2). If the follow dir and its contents exist, you should be ngen'd:

dir 'C:\Windows\assembly\NativeImages_v2.0.50727_32\Microsoft.PowerShel#' -r
Keith Hill
Keith, accepted as the answer. Sorry for the delay!
MagicAndi
Is there a way to ngen modules loaded by the profile? Such as PowerTab and PS Community Extensions?
Simon Gillbee
Yes but manually. Find the managed dlls required by the modules you load and run ngen.exe on them. Use the ngen.exe from the 2.0 framework dir e.g. `C:\Windows\Microsoft.NET\Framework64\v2.0.50727`.
Keith Hill
+2  A: 

Tracking down a performance issue like this can be tricky, but there are a few things you can do to improve / fix things.

First off, starting PowerShell cold versus warm. At least on my workstation, the first time I run PS in the morning, it takes a bit longer to launch than subsequent times. Is there a way you can keep it warm to minimize the load times?

Second, use a tool like Process Monitor from the fine folks working for Windows Sysinternals. Set it to monitor the powershell.exe process and see what it is doing that is taking so long. For me, I have a number of mapped network drives and shared scripts that get sourced from the network. In my testing, I measured about a two second delay in starting per remote script I was loading.

PowerShell does need to load a bunch of resources from disk into memory, so it should go without saying that having your I/O system perform optimally will help as well. Defrag, make sure you have ample free RAM, etc. It even queries quite a bit from the registry so you may want to ensure your registry is completely defragged - though that is quite a long shot.

Goyuix
Goyuix, thanks for pointing out the various areas to investigate. +1
MagicAndi
A: 

It may be completely unrelated but I have once had a massive pause during powershell startup.

It was somehow related to the fact that my laptop was in a domain, I then hibernated it and started it again when the laptop was not in the domain anymore. I looked at the startup with dottrace and could only see that somewhere in the initialization of Providers the code got stuck.

Restarting the machine helped in this case. Also it doesn't always happen (in fact, only once so far).

flq