Creating a Function to Test and Compare PowerShell Commands

Posted on March 24, 2015 by Jeff Hicks in PowerShell with 0 Comments

As you work with PowerShell, and especially when you begin developing scripts, you’ll realize there may be several ways to achieve the same result. How do you decide which is the better option? My first criteria is that the best choice best takes advantage of the PowerShell paradigm.

For example, you might have started with code like this, which is modeled after the way we would have used VBScript.

Ostensibly it works.

The results of our computer's properties. (Image Credit: Jeff Hicks)

The results of our computer’s properties. (Image Credit: Jeff Hicks)

 

But this isn’t really good PowerShell. This a better approach to writing our PowerShell.

Our formatted result for our modified PowerShell code. (Image Credit: Jeff Hicks)

Our formatted result for our modified PowerShell code. (Image Credit: Jeff Hicks)

 

The result is even formatted nicely. This is the first test. Unfortunately there really isn’t a quantitative way to determine that the latter approach is better. This comes from experience. So let’s assume that as you are working you have two equally valid and good PowerShell solutions to a task. Which is better? For me, the next test is legibility. That is, how easy is it to understand and follow what is happening in your code? Which makes more sense to you? Which is easier for someone else to understand? Again, this is a subjective measure.

The final standard, at least for me, is performance. Normally I don’t worry too much if one approach is a few milliseconds faster than another. Usually you can get a sense simply by running the different commands. But the best way is to actually measure the command expression and see how long each takes. Here are some simple examples.

Sponsored

The task is to check the status of a list of services on a remote computer. Being new to PowerShell, you might come up with code like this:

It works just fine.

List of services on a computer. (Image Credit: Jeff Hicks)

List of services on a computer. (Image Credit: Jeff Hicks)

 

Probably not the best PowerShell because Get-Service can accept an array of service names, which means this also works.

But let’s find out which one truly is faster. We will do this with the Measure-Command cmdlet.

The Measure-Command cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)

The Measure-Command cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)

 

Typically you use the command like this:

PowerShell runs the scriptblock,, in this case getting values from 1 to 10,000, and measures how long it takes.

Running the Measure-Command cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)

Running the Measure-Command cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)

 

The result is a TimeSpan object. As you can see from the screenshot it took almost four seconds to complete. Note that you don’t see any results from the command itself. So let’s test our two service commands.

Here’s the result:

Our test results. (Image Credit: Jeff Hicks)

Our test results. (Image Credit: Jeff Hicks)

 

Now for the other command.

Our second test result. (Image Credit: Jeff Hicks)

Our second test result. (Image Credit: Jeff Hicks)

 

Faster, but not as much as I thought. And in this case, there may be networking or server performance issues affecting the outcome. Additionally, depending on the commands you are testing, there may be a caching effect which could skew repeated tests. So while the results are meaningful you should take them in context.

Sponsored

That said, I might get better information if I test the expression several times and take the average.

Results after we've tested our code several times. (Image Credit: Jeff Hicks)

Results after we’ve tested our code several times. (Image Credit: Jeff Hicks)

 

Using a for loop, I measure how long it takes to run my scriptblock, saving the results to $Totals. To mitigate any caching or other issues, I’m sleeping for 10 seconds between each test. When finished, I can then calculate the average of the TotalMilliseconds property.

Now to test the other:

Results after calculating milliseconds. (Image Credit: Jeff Hicks)

Results after calculating milliseconds. (Image Credit: Jeff Hicks)

 

So the second approach is faster and better PowerShell.

I like the idea of testing over a number of runs an reporting an average so much I created a PowerShell function to make it easier. I call it Test-Expression.

The premise is essentially what I have just demonstrated, although the implementation is a bit advanced. This should make it easier to test and compare PowerShell commands. You can specify the number of times to test and how many seconds to sleep between tests. The following tests produce the same result but one is significantly faster than the other.

Test-Expression function results. (Image Credit: Jeff Hicks)

Test-Expression function results. (Image Credit: Jeff Hicks)

 

Compared to this:

And finally this example using new syntax in PowerShell 4.0.

You might have other requirements that make one of these more attractive than the others but at least in terms of measurable performance you can make an informed decision.

Sponsored

Tagged with , ,