Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Remote PowerShell Performance Comparison

Posted on April 5, 2010

Fellow Windows PowerShell MVP Marco Shaw clued me in on a Microsoft blog post that did a terrific job of comparing, from a performance perspective the different PowerShell 2.0 techniques you can use when managing remote computers. The results are pretty much as I would expect.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

Cmdlets with a –computername parameter tend to perform the best.  Using Get-WMIObject tend to be the slowest. Certainly your mileage may vary depending on network, servers, and the exact PowerShell expression. In between, you get pretty decent performance using Invoke-Command.  Sometimes, using Invoke-Command is the only way to accomplish a remote management task. One major point I want to re-iterate from the original blog posting is that if you need to invoke multiple commands on a remote server, create a saved PSSession and reuse the session.  Otherwise you are incurring a lot of overhead in setting up and tearing down WinRM sessions when using –computername.

My performance testing confirms the original findings. When you use –computername, when you use WMI and when you use Invoke-Command depends on what you have to accomplish. To help make it easier to calculate performance, I put together a little script that executes a PowerShell command for a remote computer a certain number of times, and calculates the average time it takes to complete.

   1: #requires -version 2.0 

   2:  

   3: Function Get-PerfTime {

   4: Param ([scriptblock]$expression,

   5:        [int]$interval=1,

   6:        [int]$max=10

   7:       ) 

   8:  

   9:     1..$max | foreach {

  10:         $i=($_/$max)*100

  11:         Write-Progress -Activity "Performance Testing" `

  12:         -Status "Repeat: $max Interval: $interval MS" `

  13:         -CurrentOperation $expression `

  14:         -PercentComplete $i

  15:         (Measure-Command -Expression $expression).TotalMilliseconds

  16:         sleep $interval

  17:     }

  18: } #end function

  19:  

  20: $computername="coredc01"

  21: #sleep interval in seconds

  22: $sleep=1

  23: #max number of tries

  24: $max=100

  25: #create a PSSession for later

  26: $session=New-PSSession -ComputerName $computername

  27:  

  28: #define a standard scriptlblock with a cmdlet that supports -computername

  29: $Test1={get-process -ComputerName $computername }

  30: #define a WMI equivalent

  31: $Test2={Get-WmiObject -Class win32_process -ComputerName $computername}

  32: #define a test using Invoke-Command

  33: $Test3={invoke-command -ComputerName $computername -ScriptBlock {$scriptblock}}

  34: #define a test with Invoke-Command and PSSession

  35: $Test4={invoke-command -Session $session -ScriptBlock {$wmiscriptblock}}

  36: $Test5={invoke-command -Session $session -ScriptBlock {$scriptblock}}

  37:  

  38: $Test1,$Test2,$Test3,$Test4,$Test5 | foreach {

  39:     $raw=Get-PerfTime -max $max -expression $_ -sleep $sleep 

  40:     $avg=($raw | Measure-Object -average).Average

  41:  

  42:     New-Object PSObject -Property @{

  43:         Computername=$computername

  44:         Repeat=$max

  45:         Expression=$_

  46:         Average=$avg

  47:         RawData=$raw

  48:     } 

  49: }

  50: #clean up the PSSession

  51: Remove-PSSession $session

  52: write-host "Finished!" -ForegroundColor Green

  53: #end of script

You know I love objects, so my little script writes a custom object to the pipeline for each tested expression.

Average      : 19.406741

RawData      : {18.6137, 19.1951, 19.4136, 20.8938...}

Expression   : get-process -ComputerName $computername

Computername : coredc01

Repeat       : 100

I also added a sleep interval for whatever it might be worth. I know there’s some caching with WMI, but you’d probably likely need a sleep interval of several minutes for it to clear. The object also returns the raw response times if you want to do something else with them. I already calculate the average using Measure-Object. You might use the script like this.

PS S:\> $results=.\PerfCompare.ps1

PS S:\> $results | sort Average | format-table Average,Expression -AutoSize

   Average Expression

   ------- ----------

  11.87756 invoke-command -Session $session -ScriptBlock {$Test1}

12.119081 invoke-command -Session $session -ScriptBlock {$Test2}

19.406741 get-process -ComputerName $computername

64.133741 Get-WmiObject -Class win32_process -ComputerName $computername

593.375884 invoke-command -ComputerName $computername -ScriptBlock {$Test1}

One interesting thing to note here is that Invoke command with the original script block ({get-process}) was faster than calling Get-Process –computername. This was over a 100 count loop with a sleep interval of 1 second. I’d be very curious to see how your numbers compare.


Behind the PowerShell Pipeline
Download PerfCompare.ps1

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

2 thoughts on “Remote PowerShell Performance Comparison”

  1. Pingback: uberVU - social comments
  2. Jose Barreto says:
    April 6, 2010 at 8:46 am

    Careful with Invoke-Command. if you use a command like

    $a=”dir”
    Invoke-Command{$a}

    It’s not going to actually execute the “dir” commadd and give you a list of files. It will simply output the string “dir”. Obviously, that executes pretty quickly…

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d