- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
The Measure-Commandcmdlet couldn't be simpler. It only has two parameters: Expressionand InputObject. In fact, InputObjectjust represents one or more expressions anyway. It's simple in nature but provides useful metrics to give you a glimpse into the performance of your code.
Let's use Measure-Commandin a real-world performance-tuning example. Some people know that not all arrays in PowerShell are created equal. Did you know that every time you add an element to an existing array using +=, you're actually destroying it and creating it again, and it's reallyslow? Let me prove it.
Say I have an array defined as $arr($arr = @()). I then add a whole bunch of elements to it. To keep it simple, I'll use some integers created with a range. I'll then add each of these numbers to the array using +=.
$arr = @() 0..25000 | ForEach-Object { $arr += $_ }
This takes awhile but how long is awhile? Let's find out with Measure-Command. We can wrap the code inside a scriptblock representing an expression and use that as the Expressionparameter for Measure-Command.
Measure-Command -Expression { 0..25000 | ForEach-Object { $arr += $_ }}
Notice that Measure-Commandreturns time broken down into various categories. We don't need to perform math to convert the time to seconds, minutes, or hours. It's all part of the object Measure-Commandreturns.
If we need to reference total seconds, we'd just reference the TotalSecondsproperty. Need that in minutes? Just find the property. We could assign the output of Measure-Commandto a variable and reference all the properties we need.
$slow_performance = Measure-Command -Expression { 0..25000 | ForEach-Object { $arr += $_ }}
Let's now use the quicker way of adding elements to an array by using an ArrayListand see how fast that is.
$arr = [System.Collections.ArrayList]@() $fast_performance = Measure-Command -Expression { 0..25000 | ForEach-Object { $arr += $_ }}
It's a lot faster! We have real numbers using Measure-Command. We can even calculate how much faster it is using the numbers we retrieved from Measure-Command. You can see below that by using an ArrayListover an array, we were able to perform the same task 135 times faster! These numbers wouldn't be possible without Measure-Command'sgranular time metrics.
Subscribe to 4sysops newsletter!
PS> [math]::Round($slow_performance.TotalSeconds / $fast_performance.TotalSeconds,0) 135
Measure-Commandis one of those PowerShell cmdlets that is simple yet extremely useful. This cmdlet can provide real numbers to any piece of code (expression). This gives you the data you can then compare with other methods to tune your scripts to be as fast as possible.
Did fast_performance really take 2 days? Seems that field should more often than not be zero, but that’s not the case… Ever.
@Kevin
Very small values are displayed using scientific notation:
This optimization didn't work for me. Running both as an array and as an ArrayList came out identical. I did open separate instances of PS to ensure the variables for $arr were different as well. Any ideas of what may be going on?
Win10, PS v5.1
Because the two commands are exactly the same…
Yep, this example of array performance is bogus. The times for both are the same. But the practical example of the measure-command is good 🙂