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

PowerShell Performance Series Part 3 (.NET method call not always faster as PowerShell shortcut)

Continuing  on from Karl's post's :

  • Fast New PSCustomObject.
  • generating a "PropertyBag" aka PScustomObject in C#
  • Getting serious about performance in PowerShell.

    and mine

  • PowerShell Performance Series Part 2 (Get-PerformanceHistory.ps1)
  • PowerShell Performance Series Part 1 (Warming Up)

    I did go on from Karl's last post Fast New PSCustomObject. where he used a HashTable to add the Properties and questioned the performance, so I converted his sample to a CTP2 Add-Type example and tested generating the Hashtable with an added method to ObjGen to create a HashTable, so to get a nice way in code to create the HashTable that is still performant.

    I got some nice results again :

    1. Creating HashTables with @{} does not preserve order (know issue) see output below
    2. creating a HashTable from objGen and adding properties to it slows down considerable
    3. Using the PowerShell Shortcut, just assigning the values to non existing properties (very convenient ) , is actually faster as using the Add method  and brings back speed to comparable speed with Karl's method :

    Especialy 3 item did surprise and pleasure me

    image

    As you can see from the output above just assigning the not existing properties in the HashTable is faster as using the Add method, so this method looks better in Code AND is faster so a win-win situation

    Lesson learned, convenient shortcuts are not always slower  

    My testing code :

    
    $class = @"
    public static class ObjGen
    {
    
      public static System.Collections.Hashtable GetHashTable (){return new System.Collections.Hashtable(); }
    
      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;
      }
    }
    "@
    
    add-type $class
    
    . c:\powershell\Get-PerformanceHistory.ps1
    
    1..50000 |% {[ObjGen]::GetPSObject($null)}
    1..50000 |% {new-object PSObject}
    
    .{
      [ObjGen]::GetPSObject(@{name="karl";age=31;now = [datetime]::Now}) | out-host
    
      $p = [ObjGen]::GetHashTable()
      $p.Add("name","karl")
      $p.add("age",31)
      $p.add("now",[datetime]::Now)
      [ObjGen]::GetPSObject($p) | out-host
    
      $p = [ObjGen]::GetHashTable()
      $p.name = "karl"
      $p.age = 31
      $p.now = [datetime]::Now
      [ObjGen]::GetPSObject($p) | out-host
    }
    
    1..50000 |% {[void][ObjGen]::GetPSObject(@{name="karl";age=31;now = [datetime]::Now})}
    
    1..50000 |% {
      $p = [ObjGen]::GetHashTable()
      $p.Add("name","karl")
      $p.add("age",31)
      $p.add("now",[datetime]::Now)
      [void][ObjGen]::GetPSObject($p)
    }
    
    1..50000 |% {
      $p = [ObjGen]::GetHashTable()
      $p.name = "karl"
      $p.age = 31
      $p.now = [datetime]::Now
      [void][ObjGen]::GetPSObject($p)
    }
    
    Get-PerformanceHistory 6
    
    # h | select com*,{[datetime]$_.EndExecutionTime - [datetime]$_.StartExecutionTime}

    Also testing showed the HashTable method of Objgen is realy not needed as the @{} construct for hashtables PowerShell  is also faster as this method.

  • 4.45300 0.00009 1..50000 |% {$p = [ObjGen]::GetHashTable()}
    4.11800 0.00008 1..50000 |% {$p = @{}}
     

    but using New-Object for this is a bad plan :

    16.32000 0.00033 1..50000 |% {$p = new-object hashtable} 

    * Update * PowerShell V1 users can test the "hashTable adding difference" by running these 2 lines and comparing them

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

    1..50000 |% {$p = @{};$p.name = "karl";$p.age = 31;$p.now = [datetime]::Now} 

    Enjoy,

  • Greetings /\/\o\/\/  

  • Published Sunday, June 15, 2008 11:14 AM by MoW
    Filed under: ,

    Comments

    # Interesting Finds: June 16, 2008

    Monday, June 16, 2008 9:33 AM by Jason Haley

    # 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

    Monday, June 16, 2008 2:03 PM by The PowerShell Guy
    Anonymous comments are disabled