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