When writing a PowerShell script, two options are available:
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#.
NET is a developer platform made up of tools, programming languages, and libraries for building many different types of applications. On the other hand, PowerShell is detailed as "A task automation and configuration management framework". A command-line shell and scripting language built on . NET.
NET Framework and that cmdlets and the objects passed along a Windows PowerShell pipeline are . NET objects. Windows PowerShell provides syntax that allows you to create . NET objects and then explore the members of those .
A cmdlet is a lightweight command that is used in the PowerShell environment. The PowerShell runtime invokes these cmdlets within the context of automation scripts that are provided at the command line. The PowerShell runtime also invokes them programmatically through PowerShell APIs.
A cmdlet is a single command that participates in the pipeline semantics of PowerShell. This includes binary cmdlets, advanced script functions, CDXML, and Workflows. Advanced functions allow you create cmdlets that are written as a PowerShell function.
When writing a Powershell script, two options are available:
- Call a cmdlet
- 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 :-)
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With