How do you control the CPU usage of a process using PowerShell?

I am trying to write a PowerShell script to track% of CPU usage by a SQL Server process. I would like to record snapshots of this number every day so that we can track it over time and monitor trends.

My research on the internet says that this WMI request should give me what I want:

Get-WmiObject -Query "SELECT PercentProcessorTime FROM win32_PerfFormattedData_PerfProc_Process WHERE Name='SqlServr'" 

When I run a WMI request, I usually get a value somewhere between 30-50% enter image description here

However, when I look at a process in Resource Monitor, it usually has average values ​​when using less than 1% of the processor SQL Server Average CPU Utilization

I know that a WMI request just returns a snapshot of the CPU usage, not the average over a long period of time, so I know that they are not directly comparable. However, I think the snapshot should be less than 1%, as the average monitor resource is less than 1%.

Does anyone have any ideas on why there is such a big mismatch? And how can I get an accurate measurement of CPU usage for a process?

+7
source share
3 answers

Everything I learned about WMI and performance counters in the last couple of days.

WMI stands for Windows Management Tool. WMI is a set of classes registered in the WMI system and the Windows COM subsystem. These classes are known as providers and have any number of public properties that return dynamic data when requested.

Windows comes preloaded with a large number of WMI providers that provide you with information about the Windows environment. On this issue, we are dealing with suppliers of Win32_PerfRawData * and two wrappers that build it.

If you request any Win32_PerfRawData * provider directly, you will notice that the numbers returned by them look scary. This is because these providers provide source data that you can use to calculate what you want.

To simplify work with Win32_PerfRawData * providers, Microsoft has provided two wrappers that return better answers when requested, the PerfMon and Win32_PerfFormattedData * providers.

So how do we get the% processor utilization process? We have three options:

  • Get a nicely formatted number from the Win32_PerfFormattedData_PerfProc_Process provider.
  • Get a nicely formatted number from PerfMon
  • Calculate% CPU usage for yourself using Win32_PerfRawData_PerfProc_Process

We will see that there is an error with parameter 1, so it does not work in all cases, even if it is the answer usually provided on the Internet.

If you want to get this value from Win32_PerfFormattedData_PerfProc_Process, you can use the query mentioned in the question. This will give you the sum of the PercentProcessorTime value for all of these process threads. The problem is that this amount can be> 100 if there is more than 1 core, but this property is maximized by 100. Thus, as long as the sum of all these process flows is less than 100, you can get the answer by dividing the process PercentProcessorTime by the number of machine cores.

If you want to get this value from PerfMon in PowerShell, you can use Get-Counter "\Process(SqlServr)\% Processor Time" . This will return a number between 0 - (CoreCount * 100).

If you want to calculate this value for yourself, the PercentProcessorTime property in the Win32_PerfRawData_PerfProc_Process provider returns the time of the processor that this process used. So, you will need to take two snapshots, which we will call s1 and s2. Then we execute (s2.PercentProcessorTime - s1.PercentProcessorTime) / (s2.TimeStamp_Sys100NS - s1.TimeStamp_Sys100NS).

And that is the last word. Hope this helps you.

+8
source

Your hypothesis is almost correct. One thread (and the process will always have at least one thread) can have no more than 100% for PercentProcessorTime , but:

  • A process can have multiple threads.
  • A system can have several (logical) processor cores.

Therefore, here (Intel i7 processor with hyper-thread) I have 8 logical cores, and the top 20 threads (filtered totals) show (with a little utilization to make it readable):

  PS> gwmi Win32_PerfFormattedData_PerfProc_Thread | 
     ? {$ _. Name -notmatch '_Total'} | 
     sort PercentProcessorTime -desc | 
     select -first 20 | 
     ft -auto Name, IDProcess, IDThread, PercentProcessorTime

 Name IDProcess IDThread PercentProcessorTime
 ---- --------- -------- --------------------
 Idle / 6 0 0 100
 Idle / 3 0 0 100
 Idle / 5 0 0 100
 Idle / 1 0 0 100
 Idle / 7 0 0 96
 Idle / 4 0 0 96
 Idle / 0 0 0 86
 Idle / 2 0 0 68
 WmiPrvSE / 7 # 1 7420 6548 43
 dwm / 4 2260 6776 7
 mstsc / 2 # 1 3444 2416 3
 powershell / 7 # 2 6352 6552 0
 conhost / 0 # 2 6360 6368 0
 powershell / 5 # 2 6352 6416 0
 powershell / 6 # 2 6352 6420 0
 iexplore / 7 # 1 4560 3300 0
 Foxit Reader / 1 736 5304 0
 Foxit Reader / 2 736 6252 0
 conhost / 1 # 2 6360 1508 0
 Foxit Reader / 0 736 6164 0

all of which should contain about 800 for the last column.

But note that all are rounded to integers. Compare with the CPU Process Explorer column (which does not round when View | Show Fractional CPU is selected) for several processes. Please note that, like win32_PerfFormattedData_PerfProc_Process , the percentage value is normalized to calculate the kernel (and this is only part of the display):

Many processes use several hundred thousand cycles, but not enough to round to one percent.

enter image description here

+5
source

Have you tried Get-Counter ?

 PS PS:\> Get-Counter "\Processus(iexplor*)\% temps processeur" Timestamp CounterSamples --------- -------------- 17/07/2012 22:39:25 \\jpbhpp2\processus(iexplore#8)\% temps processeur : 1,5568026751287 \\jpbhpp2\processus(iexplore#7)\% temps processeur : 4,6704080253861 \\jpbhpp2\processus(iexplore#6)\% temps processeur : 0 \\jpbhpp2\processus(iexplore#5)\% temps processeur : 4,6704080253861 \\jpbhpp2\processus(iexplore#4)\% temps processeur : 0 \\jpbhpp2\processus(iexplore#3)\% temps processeur : 0 \\jpbhpp2\processus(iexplore#2)\% temps processeur : 0 \\jpbhpp2\processus(iexplore#1)\% temps processeur : 1,5568026751287 \\jpbhpp2\processus(iexplore)\% temps processeur : 0 

Be careful, it depends on your test:

 PS PS:\> Get-Counter -ListSet * | where {$_.CounterSetName -contains "processus"} 
0
source

All Articles