3 ways to measure your Powershell script's speed
- select the contributor at the end of the page -
As an efficiency freak, I’ve been known to time scripts down to the millisecond, compare another method and then use the method that’s just a hair faster. I’m consistently asking myself, Is this the best, most efficient way to solve this problem? It’s a good trait to have, as it forces me to not only solve a problem, but also ensures that it’s the best possible solution. So, let's take a look at why speed matters so much and how you can start measuring the efficiency of your own scripts.
Why speed matters
Let’s say you’ve just spent hours on an extraordinary script that cranks out a widget in no time flat. Shortly after, you’re browsing around the Internet only to find that someone created a script that cranked out the exact same widget in just half the time. Blast! That’s not possible, right?! Suddenly you're thinking, My script is more efficient, so how can this other guy’s script be so much faster? I’ll prove that my script is better! You then commence to running them side by side and realize you can't detect a difference at all. It seems like they’re identical. How can this guy claim his script is so fast? The reason may be that Powershell can crank out a single widget in the blink of an eye -- and you can’t tell which method is faster by just starting them at the same time and observing the results. A beginner may immediately dismiss this and move on, but an expert will dig further. An expert may think, My script appears to crank out a widget at the same time. However, this script needs to eventually crank out 1,000,000 widgets at a time. Even if you can’t tell whether that other method is faster right now, it will be important down the road. Look ahead to when your script is expected to crank out those 1,000,000 widgets, and it takes 83 minutes to run, while that other guy’s script is cranking out the exact same widgets in just 42 minutes time (time is money, right?).
Three ways to measure your speed
What’s the best way to settle this dispute? We’ve got a few options here. Each has it’s benefits and setbacks. Let's take a look:
- The .NET Stopwatch class
1. The Measure-Command cmdlet
Measure-Command is a great Powershell cmdlet to quickly find how much a piece of code takes to execute. Let me give you a classic example of getting the same thing done with different methods; the comparison of using the
Foreach-Object cmdlet with the pipeline, and the
foreach statement. Each do the exact same thing, for the most part, yet they have very different speeds. With
Measure-Command you can see that I just wrapped it around the code block and output how long that code took to execute. In this situation, you’ll see that you’d probably never be able to tell whether
foreach is faster to the naked eye when processing 1,000 items. But as soon as you wrap that code block with
Measure-Command and see the elapsed milliseconds, you’d soon see that the
foreach statement is nearly four times as fast! That’s four times the widgets in the same amount of time.
2. Differencing a [datetime] object
Going with the
ForEach-Object example I’ve, again, timed the execution. You’ll notice that this method isn’t quite as straightforward as using
Measure-Command. We must first set a variable at the top of the script, set a variable at the bottom of the script and perform some arithmetic to get the difference in the two values. It works, but it’s not quite as clean in appearance. This method would also not work if your code block takes longer than a single second, because the Millisecond property is just representing the current milliseconds since the last second passed.
3. The .NET Stopwatch class
If you’re serious about getting accurate time calculations for your Powershell scripts, the Stopwatch Class is the way to go. The Stopwatch class is an extremely handy way to time your scripts. The Stopwatch class is used just like you’d expect a physical stopwatch. It starts, constantly keeps the time since it was last started and can be stopped at any moment. I’ve taken a screenshot here of some of its behaviors. You’ll see all it takes is to instantiate the
[system.diagnostics.stopwatch] class and issue the
startNew() method. This starts the stopwatch and it begins to keep the time since that happened. You’ll see after you’ve started it, it has an
Elapsed property, which includes just about every time increment you’d like to see, the
IsRunning property and finally the
Stop() method which stops the time-keeping, but leaves the
$StopWatch variable so you can reference it at a later time. Finally, notice the last few lines. You’ll see that the
TotalMinutes property doesn’t change after the stopwatch has been stopped. This is different than using a
[datetime] object described above. It’s obvious that the stopwatch class is made for timing. It has all of the properties you’d need to accurately time any script or code block you need. Just start a new stopwatch and stop it as you desire.
Now that you've seen a few ways to measure time in your Powershell script, you have humbling proof that your script is, indeed, slower than that other guy's. It’s now time for you to leave a comment for that kind soul and commend him on his expert script-writing talents and to admit defeat.