Function to speed-up the execution of the first PowerCLI cmdlet
February 18, 2012 7 Comments
Last year there was a post on the PowerCLI Team blog called How to speed-up the execution of the first PowerCLI cmdlet. That post showed commands you need to execute to pre-compile some of the PowerCLI code to prevent this from being done in every PowerCLI session.
Running these commands will speed-up the execution of the first PowerCLI cmdlet you run in your session. The blog post was made before PowerCLI 5.0 was released and didn’t show the commands to speed-up PowerCLI 5.0. Later there was a post at the vNugglets blog Speed Up First PowerCLI 5 cmdlet — Precompile XMLSerializers that shows the commands needed for PowerCLI 5.0.
But what happens when PowerCLI 5.1 or 6.0 is released? Of course we can try to find the new commands needed to speed-up PowerCLI every time a new version is released. But would it not be easier if we have a function that will do this for you?
The Install-PowerCLIXmlSerializer function presented in this post will show you a PowerShell function that you need to run once after you install a new PowerCLI version to speed-up the execution of the first cmdlet every time you run PowerCLI.
The Install-PowerCLIXmlSerializer function
The Install-PowerCLIXmlSerializer function searches in the Global Assembly Cache on your computer for all the PowerCLI XML Serializers available. Then the function will pre-compile all these PowerCLI XML Serializers.
After the installation of a new PowerCLI version you have to run this function once. If you us both the 64-bit and 32-bit PowerCLI versions then you have to run this function once in both the 32-bit and 64-bit version of PowerCLI.
Make sure you run the Install-PowerCLIXmlSerializer function in a PowerShell session that you “Run as Administrator”.
function Install-PowerCLIXmlSerializer { <# .SYNOPSIS Installs all the PowerCLI XmlSerializers. .DESCRIPTION Installs all the PowerCLI XmlSerializers. This is needed to speed-up the execution of the first PowerCLI cmdlet that is run in a PowerCLI session. After you install a new version of PowerCLI you only have to run this function once. If you use both the 32-bit and the 64-bit version of PowerCLI then you have to run this function in both versions. You must run this function with administrative privileges enabled. .EXAMPLE PS C:\> Install-PowerCLIXmlSerializers .INPUTS None .OUTPUTS System.String .NOTES Author: Robert van den Nieuwendijk Date: 18-2-2012 Version: 1.0 #> # Create an alias for ngen.exe Set-Alias ngen (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()) ngen.exe) # Install all the PowerCLI XmlSerializers Get-ChildItem -Path $env:SystemRoot\assembly\GAC_MSIL\VimService*.XmlSerializers | ` ForEach-Object { if ($_) { $Name = $_.Name Get-ChildItem -Path $_ } } | ` Select-Object -Property @{N="Name";E={$Name}},@{N="Version";E={$_.Name.Split("_")[0]}},@{N="PublicKeyToken";E={$_.Name.Split("_")[-1]}} | ` ForEach-Object { if ($_) { ngen install "$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)" } } }
Listing 1. PowerShell Install-PowerCLIXmlSerializer function to speed-up the execution of the first PowerCLI cmdlet you run in your PowerCLI session.
Thanks for the function Robert.
Should you un-install the pre 5.1 versions or are they still required?
For example I have:
VimService25.XmlSerializers
VimService40.XmlSerializers
VimService41.XmlSerializers
VimService50.XmlSerializers
Hi Tim,
as you can see in the post on the PowerCLI Team blog that I mentioned, you need to install all the versions. So you should not uninstall them.
Kind regards,
Robert van den Nieuwendijk
I have been using this function and it works great. However, I have found a scenario where it doesn’t appear to be improving performance. I have a Windows 2008 R2 server running PowerCLI 5.1 Release 1 build 793510 where performance of the first PowerCLI command is still slow — but only when using 64-bit powershell sessions. The performance does improve for the 32-bit powershell session on the same server. Has anyone else seen similar behavior?
I found that I needed to also compile the 64 bit version too:
putting this after the set-alias for ngen:
$TargetWMI = @{
Win32_Processor = Get-WmiObject -Class Win32_Processor
} # end hash
if ($TargetWMI.Win32_Processor.AddressWidth -eq 64) {
Set-Alias ngen64 (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory() -replace “Framework64”, “Framework”) ngen.exe)
} # end if
putting this after where you call the current ngen install:
if ($TargetWMI.Win32_Processor.AddressWidth -eq 64) {
Write-Host “precompiling 64bit $($_.Name) $($_.Version)”
ngen64 install “$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)”
} # end if
Very nice!
@roy: Its not working with more than one processor machines. But you are right. Its necessary to compile it for 64bit as well.
I’ve changed it a bit to select the first processor (full code without surrounding function):
# Create an alias for ngen.exe
Set-Alias ngen (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()) ngen.exe)
$TargetWMI = @{
Win32_Processor = Get-WmiObject -Class Win32_Processor
} # end hash
if (@($TargetWMI.Win32_Processor)[0].AddressWidth -eq 64) {
Set-Alias ngen64 (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory() -replace "Framework64", "Framework") ngen.exe)
} # end if
# Install all the PowerCLI XmlSerializers
Get-ChildItem -Path $env:SystemRoot\assembly\GAC_MSIL\VimService*.XmlSerializers | `
ForEach-Object {
if ($_) {
$Name = $_.Name
Get-ChildItem -Path $_
}
} | `
Select-Object -Property @{N="Name";E={$Name}},@{N="Version";E={$_.Name.Split("_")[0]}},@{N="PublicKeyToken";E={$_.Name.Split("_")[-1]}} | `
ForEach-Object {
if ($_) {
ngen install "$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)"
if (@($TargetWMI.Win32_Processor)[0].AddressWidth -eq 64) {
Write-Host "precompiling 64bit $($_.Name) $($_.Version)"
ngen64 install "$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)"
} # end if
}
}
Hi Keb/Robert,
i tried your code and the line
Get-ChildItem -Path $env:SystemRoot\assembly\GAC_MSIL\VimService*.XmlSerializers
didn’t return anything, so i tried
PS C:\Windows\System32\WindowsPowerShell\v1.0> Get-ChildItem -Path C:\Windows\Microsoft.NET\assembly\GAC_MSIL\VimService
*.XmlSerializers which returned :
VimService60.XmlSerializers
from command line i did :
c:\Windows\Microsoft.NET\Framework\v4.0.30319>ngen.exe install “VimService60.XmlSerializers, Version=6.0.0.0, Culture=ne
utral, PublicKeyToken=10980b081e887e9f”
and the result is :
Microsoft (R) CLR Native Image Generator – Version 4.0.30319.33440
Copyright (c) Microsoft Corporation. All rights reserved.
All compilation targets are up to date.
should the order be first compile then Robers and yours script?
when i run your script it doesn’t print anything although i am on 64 bit machine.
any idea?
+1