While doing some performance optimisations on one our loader scripts I came across an issue of converting a System.Guid or [[Guid]] in PowerShell to a string representation. In C# I was always (and still am) using ToString() and never saw anything like a Guid property. However, for some reason in PowerShell I tended to use the Guid property (instead of ToString()). I really never thought about this before, but a Sunday like today really gave me a good excuse to have a closer look at it.
First thing to mention was, that Guid is really a script property instead of a native property as you can see in the last line (hence it is not visible in C#):
PS > $guid = [Guid]::NewGuid()
PS > $guid | gm
TypeName: System.Guid
Name MemberType Definition
---- ---------- ----------
CompareTo Method int CompareTo(System.Object value), int CompareTo( ...
Equals Method bool Equals(System.Object o), bool Equals(guid g), ...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToByteArray Method byte[] ToByteArray()
ToString Method string ToString(), string ToString(string format), ...
Guid ScriptProperty System.Object Guid {get=$this.ToString();}
Now it made me curious about the performance impact this might have when processing large data sets. So with Measure-Command I gave it a quick try.
Guid Conversion via Guid ScriptProperty
As you can see from the result (inside a virtual machine on my fours years old notebook) one single operation (including the loop overhead) took 0.02699 ms:
PS > $cMax = 5000000;
PS > $m = Measure-Command -Expression {
for($c = 0; $c -lt $cMax; $c++)
{
$null = [guid]::NewGuid().Guid;
}
};
PS > $m | Select TotalMilliseconds | ft -AutoSize;
TotalMilliseconds
-----------------
134996.4048
PS > $m.TotalMilliseconds / $cMax;
0.02699928096
Guid Conversion via ToString Method
Of course I expected the native ToString() method to be faster than the scripted one, but by a factor of more than 15: 0.0046 per single operation (again including loop overhead)! So in the case of our loader script it made a difference to replace all [Guid]::NewGuid().Guid occurences with [Guid]::NewGuid().ToString().
PS > $cMax = 5000000;
PS > $m = Measure-Command -Expression {
for($c = 0; $c -lt $cMax; $c++)
{
$null = [guid]::NewGuid().ToString();
}
};
PS > $m | Select TotalMilliseconds | ft -AutoSize;
TotalMilliseconds
-----------------
23011.7742
PS > $m.TotalMilliseconds / $cMax;
0.00460235484
