Avoiding Jitter: Jumpstarting the Exchange shell


A little trick from Jeffrey Snover over on PowerShell team blog: Speeding Up PowerShell Startup. Running the script mentioned by Jeffrey speeds up PowerShell startup times. Yes, hard to believe at first, but after having run this on a few servers, as Jeffrey says – the reaction is “Wow!”

  1. Paste the following in notepad and save it as Update-Gac.ps1 (or whatever you want to call it):

    Set-Alias ngen @(
    dir (join-path ${env:\windir} “Microsoft.NET\Framework64”) ngen.exe -recurse |
    sort -descending lastwritetime
    )[0].fullName
    [appdomain]::currentdomain.getassemblies() | %{ngen $_.location}

    Note: On x86 systems; replace Framework64 in the second line of this script with Framework.

  2. [Optional] Close all open windows
  3. [Optional] Start the Exchange Management Shell and note the time it takes to start up
  4. Run the script: .\Update-Gac.ps1 (or whatever you saved it as)
  5. Quit all open windows, start the Shell. Notice the difference?

As Jeffrey says in his blog post, the PowerShell team had a problem in Windows PowerShell v1, that caused the binaries not to be NGENed.

What’s NGEN?

Managed code exists in Common Intermediate Language (CIL). The Just In Time (JIT) compiler takes that and converts it into native code for a particular processor/platform – a process also referred to as “jitter”. If you don’t want this translation to happen at runtime, you can use NGEN.exe – the Native Image Generator – to convert managed code from the CIL to native code. Native code does not need to be compiled at run time, and thereby avoids jitter.

So how does speeding up PowerShell help Exchange?

The Shell is built on Windows PowerShell technology, and under the hood, the Exchange Management Console also executes PowerShell cmdlets. If you’re running Exchange Server 2007 on Windows Server 2003, you’re likely to see performance gains in shell start-up times after running this script. On one of my Exchange 2007 servers, EMS now starts up in as little as 2-3 seconds. Disclaimer: Your mileage may vary.

Feel free to leave feedback about results you’re seeing with this.

Bharat Suneja


Comments (20)
  1. Anthony Spiteri says:

    Nice, from 40-50 odd seconds (cold start) to 17-20 seconds.

  2. Definitely an improvement on my servers, thanks for the tip!

    But what I’m really looking for is some major enhancements to the management console interface. Perhaps a sneak peak of what’s to come with SP2? :)

  3. Michael Bell says:

    Cool trick Bharat! I am going to try that on my Exchange servers to see.

    BTW, where is my book? ;-)

  4. austinmc says:

    dude, that’s cool.  definitely sped things up for my home test environment running on a mac mini.  every second counts, and I counted from 12 secs with jitter to 4 without.

  5. Kelvin Bailey says:

    From 30 seconds to less than 5. Great, but why isn’t this run as part of the setup process? And why is the code not native in the first place if pretty much every Exchange server in existence is x64/x86…?

  6. Mike Crowley says:

    You mention Windows 2003.  Is this also applicable on Windows 2008, or is it builtin or something?

  7. MikeB says:

    I get a lot of errors about not being able to locate Exchange related assemblies – mainly because it’s looking for things that are not filenames. Running this under a standard powershell session on the other hand, does wonders.

    We’ve had this script in our script repository for a good while now, and it’s semi-standard practice to run it during the build of a new system.

    @Kelvin: As I understand it, it’s a ‘bug’ in the way powershell is installed that causes this process to not get run when it normally would. I believe it’s fixed in v2.

  8. Paul says:

    Ran as instructed but no real improvement.  But then again my shells were already opening in 3-5 seconds.

  9. Carol says:

    Ran the script and wow! PS load times went from 30-40 seconds to less than 5 seconds.

  10. Mark says:

    Can someone confirm that applying this wont cause problems when we come to apply exchange patchesservice packspowershell updates? Will the newer assemblies that come along with any patches "overwrite" the ones that have been etched into the gac without errors and calls to PSS?

  11. Bharat Suneja says:

    @Kelvin: As stated in Jeffrey’s post, it’s a PowerShell v1.0 issue, corrected in PS v2.0.
    (Note, Exchange Server 2007 requires PS v1.0.)

    @Mark: This simply performs the task of compiling to native code in advance, rather than at run time. You should not have issues with patches as a result of this.

  12. Steve says:

    Are you guys running this script in the EMS or just standard PowerShell?

    If you run this script in EMS, you get heaps of errors on ‘assemblies unable to load’ and ‘file not found’ errors. If you run this in standard PowerShell, you don’t get any errors, and the script finishes in a few seconds.

    Either way, the EMS and EMC startup times have not improved for me. It’s still 40-50sec slow. Am I somehow screwing up in executing the script?!

  13. Satguru says:

    hi Bharat..is there also a way to "undo" this change for powershell once this has been done?

  14. Babul says:

    Fantastic!  Speed up several servers from 30-45 seconds to less than 5!  As Steve said above, run the script from the standard PowerShell prompt to avoid the errors.

  15. Bharat Suneja says:

    @Steve: The errors can be safely ignored.

    @Satguru: Investigating if there’s a way to "undo" – although I haven’t come across a situation where this would be required. Will post update in these comments if I have something to report. :)

  16. Cis says:

    It took me at first 10 seconds to start, now 5. Not a really important improvement, but oh well, it saves me some lifetime in total over a year :)

    Thank you for the script.

  17. drac says:

    this seems to speed up DPM 2007 mgmt shell also. cool.

  18. Mike says:

    Thks!!!!

  19. Sam says:

    nice…. what’s the code to disable?

Comments are closed.