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:

  1. The Measure-Command cmdlet
  2. A [datetime] object
  3. 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. foreach-compare 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-Object or 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. datetimedifference 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. stopwatch 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.

Takeaway

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.

Get our content first. In your inbox.

Loading form...

If this message remains, it may be due to cookies being disabled or to an ad blocker.

Contributor

Adam Bertram

is an independent consultant, technical writer, trainer and presenter. Adam specializes in consulting and evangelizing all things IT automation mainly focused around Windows PowerShell. Adam is a Microsoft Windows PowerShell MVP, 2015 powershell.org PowerShell hero and has numerous Microsoft IT pro certifications. He is a writer, trainer and presenter and authors IT pro course content for Pluralsight. He is also a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at his site listed below or on Twitter at @adbertram.