Add to Technorati Favorites
Welcome to ThePowerShellGuy.com Sign in | Join | Help

PowerShell Performance Series Part 4 (Version 1.0 wins this round ?)

I finally installed two simular VM's, one with PowerShell Version 1.0 and the other one with PowerShell CTP2, to do performance testing between the 2 versions.

Both VM's run a bare Windows XP SP 2 installation with .NET framework 2.0 on both (to exclude the framework from testing)

While I was translating the code in the last post PowerShell Performance Series Part 3 (.NET method call not always faster as PowerShell shortcut) to PowerShell Version 1.0, (as PowerShell 1.0 has no add-type Cmdlet I did the same thing using the .NET framework directly) so that I could use the same code on as well PowerShell version 1.0 as the CTP2 build.

When I started testing I got some "Strange" results PowerShell 1.0 was up till 10 times faster !

image

For reference I also did the Tests from the First post PowerShell Performance Series Part 1 (Warming Up) on both the VM's (still a win for CTP2 as expected):

Seems something happened to the $null , out-null and variable assignment, that did cost performance, I need to look into it further but hope this is a CTP thingie and that it will be faster in the final V2 version.

The Test code :

$provider = new-object Microsoft.CSharp.CSharpCodeProvider
$params = new-object System.CodeDom.Compiler.CompilerParameters 

$refs = "System.dll","C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll"
$params.ReferencedAssemblies.AddRange($refs) 
$params.GenerateExecutable = $false 
$params.GenerateInMemory = $True

$class = @"
public static class ObjGen
{
  public static System.Management.Automation.PSObject GetPSObject( System.Collections.Hashtable noteproperties )
  {
    System.Management.Automation.PSObject obj = new System.Management.Automation.PSObject();
    if (noteproperties != null) 
    {
      foreach(System.Collections.DictionaryEntry item in noteproperties)
      {
        obj.Properties.Add(new System.Management.Automation.PSNoteProperty((string)item.Key,item.Value)); 
      }
    }
    return obj;
  }
}
"@


$results = $provider.CompileAssemblyFromSource($params, $Class) 
$results 

1..50000 |% {
  $o = New-Object PSObject
  Add-Member -in $o -Name 'Name' -MemberType 'NoteProperty' -Value 'Karl'
  Add-Member -in $o -Name 'age' -MemberType 'NoteProperty' -Value 31
  Add-Member -in $o -Name 'now' -MemberType 'NoteProperty' -Value [datetime]::Now
}

for($i = 0; $i -lt 50000;$i++ ) {
  $o = New-Object PSObject
  Add-Member -in $o -Name 'Name' -MemberType 'NoteProperty' -Value 'Karl'
  Add-Member -in $o -Name 'age' -MemberType 'NoteProperty' -Value 31
  Add-Member -in $o -Name 'now' -MemberType 'NoteProperty' -Value [datetime]::Now
}

[void](1..50000 |% {[ObjGen]::GetPSObject(@{name="karl";age=31;now = [datetime]::Now})})
#1..50000 |% {[void][ObjGen]::GetPSObject(@{name="karl";age=31;now = [datetime]::Now})}
1..50000 |% {$null = [ObjGen]::GetPSObject(@{name="karl";age=31;now = [datetime]::Now})}
1..50000 |% {[ObjGen]::GetPSObject(@{name="karl";age=31;now = [datetime]::Now}) | out-null}
1..50000 |% {[ObjGen]::GetPSObject(@{name="karl";age=31;now = [datetime]::Now}) } | out-null

1..50000 |% {
  $p = @{}
  $p.Add("name","karl")
  $p.add("age",31)
  $p.add("now",[datetime]::Now)
  [ObjGen]::GetPSObject($p) | out-null
}

1..50000 |% {
  $p = @{}
  $p.name = "karl"
  $p.age = 31
  $p.now = [datetime]::Now
  [ObjGen]::GetPSObject($p) | out-null
}

1..50000 |% {
  $p = @{}
  $p.name = "karl"
  $p.age = 31
  $p.now = [datetime]::Now
  [ObjGen]::GetPSObject($p) 
} | out-null


foreach ($i in 1..50000) {
  $p = @{}
  $p.name = "karl"
  $p.age = 31
  $p.now = [datetime]::Now
  [ObjGen]::GetPSObject($p) | out-null
} 

for($i = 0; $i -lt 50000;$i++ ) {
  $p = @{}
  $p.name = "karl"
  $p.age = 31
  $p.now = [datetime]::Now
  [ObjGen]::GetPSObject($p) | out-null
}

foreach ($i in 1..50000) {
  $p = @{}
  $p.name = "karl"
  $p.age = 31
  $p.now = [datetime]::Now
  $null = [ObjGen]::GetPSObject($p)
}

foreach ($i in 1..50000) {
  $p = @{}
  $p.name = "karl"
  $p.age = 31
  $p.now = [datetime]::Now
  [ObjGen]::GetPSObject($p) > $null
}

.{foreach ($i in 1..50000) {
  $p = @{}
  $p.name = "karl"
  $p.age = 31
  $p.now = [datetime]::Now
  [ObjGen]::GetPSObject($p) 
} } | out-null

1..100000 |% {$null = $_}
for($i = 0; $i -lt 100000;$i++ ) { $Null = [String]::Copy("Now is men to come the the aid of their country" )}
for($i = 0; $i -lt 100000;$i++ ) { $a = [String]::Copy("Now is men to come the the aid of their country" )}

h | select com*,{[datetime]$_.EndExecutionTime - [datetime]$_.StartExecutionTime}

*Disclaimer* your results may vary, I don't completely believe mine yet, hence I'm scarce on conclusions in this post, and am open to any ideas why the CTP2 build does lose from Version 1.0 here ;-)

Enjoy,

Greetings /\/\o\/\/

Published Monday, June 16, 2008 2:03 PM by MoW
Filed under: , ,

Comments

# re: PowerShell Performance Series Part 4 (Version 1.0 wins this round ?)

Marc, I actually wrote about performance tuning PowerShell scripts some time back...may not be what you're expecting though :)

http://www.pseale.com/blog/PowerShellPerformanceTuningAHelpfulScript.aspx

Monday, June 16, 2008 3:32 PM by Peter
Anonymous comments are disabled