5

When writing a PowerShell script, two options are available:

  1. Call a cmdlet
  2. Use the .NET Framework Class library

In the background, cmdlets are more than probably making use of the .NET library.

Which of both is better to use in a Powershell script, performance wise?

I tend to better like direct use of the .NET library since it's closer to C#.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Spack
  • 464
  • 4
  • 22
  • 5
    Calling a .NET method directly is faster and carries less overhead than invoking a cmdlet (which is, in itself a .NET object, which then eventually wraps a call to some .NET method). That doesn't mean that your scripts are gonna be "better" if you replace all cmdlets with a long string of direct method calls – Mathias R. Jessen Apr 20 '17 at 13:58
  • 2
    @Mathias beat me to it, PowerShell might be doing the same thing (maybe a bit slower) but the code is infinitely more readable. – brendan62269 Apr 20 '17 at 14:01
  • 3
    @MathiasR.Jessen and brendan62269 have the right of it - go for readability/maintainability when you're dealing with scripts; if you're doing something by scripting in the first place, the absolute highest 'efficiency' of your code can't really be a consideration (or you'd be writing code in a compiled language in the first place). – Jeff Zeitlin Apr 20 '17 at 14:08
  • 1
    @BaconBits Trying to write an answer, but it's hard not going off on a tangent about the entire philosophy behind PowerShell/Monad :-P – Mathias R. Jessen Apr 20 '17 at 14:33

3 Answers3

21

When writing a Powershell script, two options are available:

  1. Call a cmdlet
  2. Use the .NET Framework Class library

TBH, I think this is a gross over-simplification of what PowerShell is.

First thing worth pointing out is that PowerShell (the API and the powershell.exe host application) is implemented in .NET in the first place, so by definition everything in PowerShell is "using .NET".

A cmdlet, as an example, is actually a .NET object - take a look at the CmdletInfo object returned by Get-Command:

PS C:\> (Get-Command Get-Command) |Format-List Name,CommandType,DLL,ImplementingType


Name             : Get-Command
CommandType      : Cmdlet
DLL              : C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad36
                   4e35\System.Management.Automation.dll
ImplementingType : Microsoft.PowerShell.Commands.GetCommandCommand

Have a look at the implementing type Microsoft.PowerShell.Commands.GetCommandCommand - it's just a regular .NET class - when you issue the command Get-Command, powershell creates an instance of this class, calls some well-defined methods, that then in turn calls the .NET methods that carry out the actual work.


The entire philosophy behind PowerShell (or Monad, as it was originally called), is that development time is better spent focusing on small self-contained units/functions that do one thing well (a monad in the original conception), much like the original philosophy behind UNIX utilities.

The idea is that once you have a framework in place for coupling these units together, you can virtually compose any program by way of connecting the simpler units.

The materialization of this idea is the cmdlet - it has some well defined behaviors for input binding that allows you to compose pipelines:

Get-AThing | Filter-TheThing | Write-ToAFile C:\path\to\file\name.ext

In my humble opinion, a pipeline like the above is way more readable than for example:

[System.IO.File]::WriteAllText('C:\path\to\file\name.ext', [System.Linq.Enumerable]::Select([Thing]::EnumerateThings(),{param([thing]$in) $in -eq $someCriteria}))

That's subjective, but what I'm trying to get at, is that you're cheating yourself out of taking advantage of some core functionality that PowerShell provides for free out of the box if you ditch cmdlet's by the way-side


Now, for the actual question: yes, calling a single .NET method directly is faster and incurs less overhead than calling a cmdlet which in turn makes PowerShell run some additional code to eventually just wrap the same .NET method call.

That being said, if you're running a newer version of PowerShell (4.0,5.0,5.1 or 6.0), the overhead will be negligible in many cases.

For example, reading a file from disk is orders of magnitudes slower than resolving a chain of .NET method calls that are already in memory (which is what PowerShell is doing transparently to you), simply because moving electrons from a spinning disk through a disk controller and a memory bus into memory is an operation bounded by the speed of light.

My personal strategy for optimizing for performance is to review the algorithms/routines and data structures I use, long before I start considering cmdlet vs. direct method call.

If I'm doing something stupid that makes my script require 10x as many CPU cycles to calculate then it won't help trying to chase marginal overhead.

If you've reached the limit with that tactic, consider writing your cmdlet's in C# or VB.NET - compiled code is (almost) always faster than interpreted code :-)

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • "The entire philosophy behind PowerShell is that development time is better spent focusing on small self-contained units/functions that do one thing well" I have questions about `Compare-Object`. :D – Bacon Bits Apr 20 '17 at 15:33
  • @BaconBits No one said every single implementation would be ideal – Mathias R. Jessen Apr 20 '17 at 15:35
  • the speed of the spinning disk probably slows you down more than the speed of light. After all, to photons, it feels like they have to wait FOREVER for the disk to get around to the point they were looking for. – NH. Nov 02 '17 at 17:59
2

The difference between the two should be minimal. The cmdlet will invoke the .NET Framework method and so the behaviour will be the same.

So you might see some extremely minor performance improvements by not using the cmdlets; but it'll be negligible.

Why not consider which reads better and stick to that?

Robin Cox
  • 41
  • 1
  • 4
  • Yes that's why I prefer calling .NET, I find it reads better than the cmdlets but of course it depends of what you trying to get done. – Spack Apr 20 '17 at 14:15
  • There it is then. Invoking .NET directly will be 'technically better' in terms of performance. If you also find that easier to read / understand then that's a win-win. – Robin Cox Apr 20 '17 at 14:17
  • When people complain about PowerShell performance, I usually see people doing "the wrong thing", for example doing nested loops when they could have used a hashtable/dictionary. In these cases, ditching cmdlets in favor of native .NET calls has (as @RobinCox points out) only a marginal performance benefit. – Mathias R. Jessen Apr 20 '17 at 14:21
0

For me, after using both, the choice really boils down to code maintenance. Scripted cmdlets allow for easier code maintenance that managed classes and there structured recompile and release.

Scripted cmdlets are my choice every time unless the processing speed is critical.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
raj1950
  • 1
  • 1