PowerShell Performance Series Part 1 (Warming Up)
This is the first part of a ( Multi-Blog ) series about PowerShell Performance.
In a former post, I mentioned about the task Brandon took up : PowerShell + S.DS.Protocols Versus AdFind… in this quest, preparing for his next step, the following issue came up :
What is the Quickest and most efficient way to create custom objects?
This is an important one, for PowerShell output we want objects back not text, to make the information easy to consume part of the whole point of the exercise, but I'm sure brandon will talk about that in his series.
So let's get back to the performance, creating custom objects is used often in cases we need to transform text into structured data, ( for some nice examples see my TextScraping series on this blog. )
In most cases for PowerShell scripts the speed is not the most important part, hence I never did any optimizing in the TextScraping series , but in Brandon's case when you have a lot of results you need to convert to Objects this is a crucial part.
In the past me and some other guys did a lot of performance testing on PowerShell V1 , and tried different coding methods, using raw .NET etc. and compared them, mostly while discussing them on IRC ( #PowerShell on FreeNode )
Brandon's question on the MVP list, combined with the CTP2 that has a lot of performance improvement got us going again as well on the list, IRC as now on our blog's as some nice results came up.
Me, Karl Prosser , Jaykul, Brandon of course, ( and anyone that wants to join on IRC , blog or elsewhere ) are for example testing :
- Using the pipeline
- Cmdlets
- Raw .NET
- Function calls
- Cmdlet calls
- V1 agains V2
- all else that comes up.
And we will post some of the results to our blogs, as not only some might surprise you, but also as they can help you to pick the right solution for the right Task.
As New-Object , came out as the main bottleneck Karl made some .NET tests in PowerShell V1 that he will post on his blog later, but as I could easy test this in V2 by using Add-Type ( See . PowerShell V2 CTP2 : making Custom Enums using add-Type and Jeffrey Snover's post about it on the PowerShell team blog. for a bit more information.
I used the same method to make my own "Object Generator" Class to create new custom objects in PowerShell V2 CTP, and compared using that class to "generate" the Objects agains using the new-Object Cmdlet
$class = @"
public static class ObjGen
{
public static System.Management.Automation.PSObject GetPSObject (){return new System.Management.Automation.PSObject(); }
}
"@
add-type $class
1..10000 |% {[ObjGen]::GetPSObject()}
1..10000 |% {new-object PSObject}
h | select com*,{[datetime]$_.EndExecutionTime - [datetime]$_.StartExecutionTime}
if you paste this code in a PowerShell CTP2 console you get results like this :
1..10000 |% {[ObjGen]::GetPSObject()} 00:00:03.8390000
1..10000 |% {new-object PSObject} 00:00:06.6640000
for($i=0;$i -lt 10000;$i++ ) { [ObjGen]::GetPSobject() } 00:00:03.0840000
you see a big time gain , but it was way less as Karl's results (in 10 X difference range), but we could only compare difference as we where on different machines, Karl is going to set up 2 identical VM's with PowerShell version1 on one, and the PowerShell CTP2 on the other to give better comparisons, so lookout for more info about this on Karl's blog later (I will link them here).
another interesting example that Karl throw up on the IRC Channel, and that is usable on PowerShell Version 1.0 and on PowerShell CTP2
function dummy { }
1..50000 | % { dummy }
1..50000 | % { $obj = 1 }
for($i = 0; $i -lt 50000;$i++ ) { dummy }
for($i = 0; $i -lt 50000;$i++ ) { $obj = 1 }
1..50000 | &{ process {dummy} }
function k% ([scriptblock]$sb){process {&$sb }}
1..50000 | K% { dummy }
h | select com*,{[datetime]$_.EndExecutionTime - [datetime]$_.StartExecutionTime}
My results on PowerShell CTP2 are this :
function dummy { } 00:00:00.0030000
1..50000 | % { dummy } 00:00:05.1140000
1..50000 | % { $obj = 1 } 00:00:03.9240000
for($i = 0; $i -lt 50000;$i++ ) { dummy } 00:00:01.1110000
for($i = 0; $i -lt 50000;$i++ ) { $obj = 1 } 00:00:00.1220000
1..50000 | &{ process {dummy} } 00:00:01.4830000
function k% ([scriptblock]$sb){process {&$sb }} 00:00:00
1..50000 | K% { dummy } 00:00:08.7700000
If you have PowerShell Version 1.0 running paste in the same Lines in the PowerShell console and compare them with mine.
Call for Action !! : Paste the code above into a PowerShell V1 or CTP2 console also and post your results in the Comments indicating what version you did use , would be nice to compare results.
*Edit* I got this by mail from Doug Finke ( Development in a Blink )
Your comments are disabled.
My machine is 2GB dual core running Vista as the host and has Version 1 PowerShell
Version 2 CTP2 is an XP VPC.
Thanks Doug ! ,
and for the comments I had to disable anonymous comments because of to much spam, but you can leave comments if registered (very simple and no personal data needed)
to be continued ;-)
Enjoy,
Greetings /\/\o\/\/