{"id":6761,"date":"2008-01-28T17:51:00","date_gmt":"2008-01-28T17:51:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2008\/01\/28\/lightweight-performance-testing-with-powershell\/"},"modified":"2019-02-18T13:16:15","modified_gmt":"2019-02-18T20:16:15","slug":"lightweight-performance-testing-with-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/lightweight-performance-testing-with-powershell\/","title":{"rendered":"Lightweight Performance Testing with PowerShell"},"content":{"rendered":"<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">When you write a script, a few possible concerns may be going through your mind:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoListBulletCxSpFirst\"><span><font size=\"3\">\u00b7<\/font><\/span><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><font size=\"3\"><span>Does my Script do what I want it to?<\/span><span><\/span><\/font><\/font><\/p>\n<p class=\"MsoListBulletCxSpMiddle\"><span><font size=\"3\">\u00b7<\/font><\/span><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><font size=\"3\"><span>Can the script be read and understood by other people?<\/span><span><\/span><\/font><\/font><\/p>\n<p class=\"MsoListBulletCxSpMiddle\"><span><font size=\"3\">\u00b7<\/font><\/span><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><font size=\"3\"><span>Is the script efficient?<\/span><span><\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><\/font><\/font>&nbsp;<\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">The answers to one and two can be very subjective, so today I\u2019ll help you figure out how to make your script efficient.<span>&nbsp; <\/span>More precisely, I will help you to figure out the most efficient of a few different ways you can do something in Powershell.<span><\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Making efficient Powershell scripts can be tricky.<span>&nbsp; <\/span>Many things that you can do in PowerShell with a Cmdlet, you can also do with a .NET or COM object or with a command line.<span>&nbsp; <\/span>Also, some things within the Powershell language will have the same effect, but use different syntax and have slightly different performance.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Today, I\u2019ll take a scenario that you can accomplish in multiple ways in PowerShell and I\u2019ll show you how you can use Get-History or Measure-Command to do simple performance testing of what you just run, in order to help optimize your scripts.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">The scenario is common enough: Within a foreach, you want to call a method on each member of the foreach, but you also want to put each item from the foreach into a collection.&nbsp; So in order to avoid having your collection contain the items and the output from the method, you need to be able to throw away the result.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">There are basically three ways to throw away the result of a method or command: by assigning the value to $null, by casting it to [void], or by using a pipeline to send the results to Out-Null.&nbsp; Here are examples of each:<\/font><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$mycollection | foreach { $null = $_.MyMethod() ; $_ } | &lt;more cmdlet calls&gt;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$mycollection | foreach { [void]$_.MyMethod() ; $_ } | &lt;more cmdlet calls&gt;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$mycollection | foreach { $_.MyMethod() | Out-Null ; $_ } | &lt;more cmdlet calls&gt;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">I recently suggested that someone use Out-Null to do this, and a colleague challenged if this would be the fastest solution.&nbsp; So I determined that I would figure out which solution was indeed the fastest. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">It turns out language constraints are more efficient, and can be used safely provided you are using them to cast the result.&nbsp; Casting the result will not change the underlying variable\u2019s constraint.&nbsp; This only happens when you have the constraint on the left side an assignment operator, so:<span><\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">[void]$_.MyMethod() # will cast the return value of the method<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$a = [void]$_.MyMethod() # will cast the return value of the method<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">[void]$a = $_.MyMethod() # Will constraint $a to Void<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">I personally find the third example selectively useful but potentially dangerous.&nbsp; The reason comes from personal experience (I once have the third case in my script from copy\/paste and did not realize it).&nbsp; Having a throwaway variable is really useful (that\u2019s why $null exists), but having one by accident is very dangerous.<span><\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">The efficiency difference was pointed out to me, and so here is how I figured out the best (read, fastest) way to throwaway results:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">In order to do this, I determined I would perform the same operation on a moderately sized input (1000 items).<span>&nbsp; <\/span>My three tests were:<\/font><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$result = (1..1000 | % { $_.GetType() | Out-Null; $_})<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$result = (1..1000 | % { [void]$_.GetType(); $_})<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$result = (1..1000 | % { $null = $_.GetType(); $_})<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Then I ran the following item to collect the history of what I just did.<\/font><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$results =&nbsp; (Get-History)[-1..-3]<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">This collected the last three commands that I ran, by a nice little convention called negative indexing.&nbsp; In Powershell, if you pass a negative number to a list, it returns that item in the list, starting at the end.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Now if you look at a history item, it contains the start execution time and the end execution time.&nbsp; This means that I can look through my history and figure out which one was the fastest.&nbsp; This will give me that information from any list of history items:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$results | % { $_.CommandLine ; ($_.EndExecutionTime -$_.StartExecutionTime).TotalMilliseconds }<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">$result = (1..1000 | % { $null = $_.GetType(); $_})<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">218.4<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">$result = (1..1000 | % { [void]$_.GetType(); $_})<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">234<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">$result = (1..1000 | % { $_.GetType() | Out-Null; $_})<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">670.8<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><b>Note: <\/b>It is also possible to use Measure-Command to measure each of the expressions as well.&nbsp; Instead of collecting the commands and their times from the history, you can always use Measure-Command \u2013Expresson {<i>ScriptBlock<\/i>} to time how long a specific bit of Powershell code takes to run.<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\"><font size=\"3\">As you can see, <strong><i><span>Out-Null is actually the least efficient way you could choose to do this<\/span><\/i><\/strong><\/font><font size=\"3\"><em><span>.<\/span><\/em>&nbsp; It appears the winner is assigning the output of an item to the variable $null, by a margin of just shy of 16 milliseconds (mileage may vary on your boxes).<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">So the fastest way is: <\/font><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">$mycollection | foreach { $null = $_.MyMethod() ; $_ } | &lt;more cmdlet calls&gt;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">I hope this has been educational, and also helps provide you with a way to judge the faster of a few different possibilities of implementing the same script.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\"><\/font>&nbsp;<\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">James Brundage[MSFT]<\/font><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you write a script, a few possible concerns may be going through your mind: &nbsp; \u00b7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Does my Script do what I want it to? \u00b7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Can the script be read and understood by other people? \u00b7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Is the script efficient? &nbsp; The answers to one and two can be very subjective, so today [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[75],"class_list":["post-6761","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-testing"],"acf":[],"blog_post_summary":"<p>When you write a script, a few possible concerns may be going through your mind: &nbsp; \u00b7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Does my Script do what I want it to? \u00b7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Can the script be read and understood by other people? \u00b7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Is the script efficient? &nbsp; The answers to one and two can be very subjective, so today [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/6761","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=6761"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/6761\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=6761"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=6761"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=6761"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}