Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A PowerShell cmdlet vs. a .NET class

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#.

like image 923
Spack Avatar asked Apr 20 '17 13:04

Spack


People also ask

Is PowerShell and .NET the same?

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.

Are PowerShell cmdlets are .NET Framework objects?

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 .

What is a PowerShell cmdlet?

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.

What is the difference between cmdlet and function in PowerShell?

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.


2 Answers

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 :-)

like image 78
Mathias R. Jessen Avatar answered Sep 23 '22 12:09

Mathias R. Jessen


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?

like image 36
Robin Cox Avatar answered Sep 22 '22 12:09

Robin Cox