PowerShell Problem Solver: More Processor Performance

In a previous article, we began exploring techniques for gathering average processor load numbers. I demonstrated how to use WMI and PowerShell to query the Win32_Processor class. The scenario we are using is a real-world problem that someone posted in a PowerShell forum. Although you might not have this specific problem, I think you might learn a few things along the way.
PowerShell Processor Article Series:

WMI Performance Counters

Performance counter data can be accessed through WMI. This type of data if presented in both raw and formatted forms. Personally, I prefer the latter. Let’s find an appropriate class:

Listing performance formatted data classes (Image Credit: Jeff Hicks)
Listing performance formatted data classes (Image Credit: Jeff Hicks)
I've highlighted the most likely class. I can query it like any other WMI class.
​
If you try that, then you'll get multiple instances for each processor core as well as a _Total instance. You can simplify the output once you know what to look for:
Selecting key properties (Image Credit: Jeff Hicks)
Selecting key properties (Image Credit: Jeff Hicks)
Because I am interested in an average across all cores, I can filter out the _Total instance and average the rest much as I did in the previous article.
Getting a performance average (Image Credit: Jeff Hicks)
Getting a performance average (Image Credit: Jeff Hicks)
Now that I have the basic concept and syntax worked out, let's scale out to manage a list of computers.
Getting Average Percent Processor Time remotely (Image Credit: Jeff Hicks)
Getting Average Percent Processor Time remotely (Image Credit: Jeff Hicks)
In this example, I'm trying something new. The results of the Get-WmiObject command are piped to Group-Object. This will write a new object to the pipeline. The Name property will be the computername, i.e. PSComputername, because that is what I instructed PowerShell to use for the grouping. The Group property will be the collection of instances. I'm creating a custom property on the fly called Avg%ProcessorTime, which takes the PercentProcessorTime value for each instance in the group and calculates an average.

Using PowerShell's Get-Counter cmdlet

The other approach is to get actual performance counter information. Fortunately, PowerShell has a cmdlet that makes this pretty easy called Get-Counter. You can use this cmdlet to access all of the performance counters you would use through the PerfMon management console. The first step is to identify the relevant counters.
Getting processor related counters (Image Credit: Jeff Hicks)
Getting processor related counters (Image Credit: Jeff Hicks)
We can drill down and get just the list of counters.
Processor Counters (Image Credit: Jeff Hicks)
Processor Counters (Image Credit: Jeff Hicks)
Some counters exist for multiple instances as they do with the processor. If you look at the PathsWithInstances property, you'll see a counter for every processor instance.
 Processor counter paths with instances (Image Credit: Jeff Hicks)
Processor counter paths with instances (Image Credit: Jeff Hicks)
I am pointing all of this out because you need to specify the counter.
Getting local % processor time (Image Credit: Jeff Hicks)
Getting local % processor time (Image Credit: Jeff Hicks)
With me so far? For our scenario, I think all I need is the counter for _Total. The Get-Counter cmdlet displays results in an easy-to-read fashion, but not very pipeline friendly for my tastes. I think it helps to see the raw data.
Counter samples (Image Credit: Jeff Hicks)
Counter samples (Image Credit: Jeff Hicks)
Once you understand this, you can build an expression to display only what you need:
Getting remote processor time (Image Credit: Jeff Hicks)
Getting remote processor time (Image Credit: Jeff Hicks)
If you read the help for Get-Counter, which you should, you'll see that you can get a number of samples. This might give us a better overall average.
​
This expression takes a sample every five seconds for about a minute.
Getting multiple samples (Image Credit: Jeff Hicks)
Getting multiple samples (Image Credit: Jeff Hicks)
Do you see where I'm going? We can take these results and average the underlying CookedValue property.
Getting a cooked value average (Image Credit: Jeff Hicks)
Getting a cooked value average (Image Credit: Jeff Hicks)
The last step then is to scale this out for multiple servers. One thing to note is that when querying multiple servers the computer name is part of the counter sample.
Testing counter collection for multiple servers (Image Credit: Jeff Hicks)
Testing counter collection for multiple servers (Image Credit: Jeff Hicks)
The expression I'm using is a one-line expression, although you could easily break it down into multiple steps.
​
The first line is getting the processor counter for all the computers in my $computers variable, taking 12 samples over five second intervals. The second line expands the CounterSamples property and groups the results on the Path property. The end result is that all the results will be grouped by computername. On the third line I'm using Select-Object to create a few custom properties. The first is the computer name, which I am pulling out of the Name property, which is really the counter path. The last line creates another value for the average which is calculated by Measure-Object.
Getting processor time averages for many servers (Image Credit: Jeff Hicks)
Getting processor time averages for many servers (Image Credit: Jeff Hicks)
Once you have your sampling requirements figured out, this would make a good function or script to save yourself a lot of typing. We've looked at a number of techniques for getting an average processor load or utilization, but the original problem had a second requirement, which we'll look at next time.