如何使用PowerShell监视进程的CPU利用率?

时间:2021-11-22 00:39:32

I'm trying to write a PowerShell script to monitor % CPU utilization of a SQL Server process. I'd like to record snapshots of this number every day so we can monitor it over time and watch for trends.

我正在尝试编写PowerShell脚本来监视SQL Server进程的%CPU利用率。我想每天记录这个号码的快照,以便随着时间的推移监控它并观察趋势。

My research online said this WMI query should give me what I want:

我在网上的研究表明,这个WMI查询应该给我我想要的东西:

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

When I run the WMI query I usually get a value somewhere between 30-50% 如何使用PowerShell监视进程的CPU利用率?

当我运行WMI查询时,我通常会得到介于30-50%之间的值

However, when I watch the process in Resource Monitor it usually averages at less than 1% CPU usage 如何使用PowerShell监视进程的CPU利用率?

但是,当我在资源监视器中查看进程时,通常平均CPU使用率不到1%

I know the WMI query is simply returning snapshot of CPU usage rather than an average over a long period of time so I know the two aren't directly comparable. Even so, I think the snapshot should usually be less than 1% since the Resource Monitor average is less than 1%.

我知道WMI查询只是返回CPU使用率的快照,而不是很长一段时间内的平均值,因此我知道这两者不能直接比较。即便如此,我认为快照通常应小于1%,因为资源监视器的平均值小于1%。

Does anybody have any ideas on why there is such a large discrepancy? And how I can get an accurate measurement of the CPU usage for the process?

有没有人对为何存在如此大的差异有任何想法?以及如何准确测量流程的CPU使用率?

3 个解决方案

#1


9  

Everything I've learned about WMI and performance counters over the last couple of days.

我在过去几天里所学到的关于WMI和性能计数器的一切。

WMI stands for Windows Management Instrumentation. WMI is a collection of classes registered with 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 queried.

WMI代表Windows Management Instrumentation。 WMI是使用WMI系统和Windows COM子系统注册的类的集合。这些类称为提供程序,具有任意数量的公共属性,可在查询时返回动态数据。

Windows comes pre-installed with a large number of WMI providers that give you information about the Windows environment. For this question we are concerned with the Win32_PerfRawData* providers and the two wrappers that build off of it.

Windows预安装了大量WMI提供程序,可为您提供有关Windows环境的信息。对于这个问题,我们关注的是Win32_PerfRawData *提供程序以及构建它的两个包装器。

If you query any Win32_PerfRawData* provider directly you'll notice the numbers it returns are scary looking. That's because these providers give the raw data you can use to calculate whatever you want.

如果您直接查询任何Win32_PerfRawData *提供程序,您会注意到它返回的数字是可怕的。那是因为这些提供商提供了原始数据,您可以用它来计算您想要的任何数据。

To make it easier to work with the Win32_PerfRawData* providers Microsoft has provided two wrappers that return nicer answers when queried, PerfMon and Win32_PerfFormattedData* providers.

为了更容易使用Win32_PerfRawData *提供程序,Microsoft提供了两个包装器,在查询时返回更好的答案,PerfMon和Win32_PerfFormattedData *提供程序。

Ok, so how do we get a process's % CPU utilization? We have three options:

好的,那么我们如何获得进程的%CPU利用率?我们有三种选择:

  1. Get a nicely formatted number from the Win32_PerfFormattedData_PerfProc_Process provider
  2. 从Win32_PerfFormattedData_PerfProc_Process提供程序获取格式良好的数字
  3. Get a nicely formatted number from PerfMon
  4. 从PerfMon获取格式良好的数字
  5. Calculate the % CPU utilization for ourselves using Win32_PerfRawData_PerfProc_Process
  6. 使用Win32_PerfRawData_PerfProc_Process计算自己的%CPU利用率

We will see that there is a bug with option 1 so that it doesn't work in all cases even though this is the answer usually given on the internet.

我们将看到选项1存在错误,因此它在所有情况下都不起作用,即使这是通常在互联网上给出的答案。

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 this process's threads. The problem is that this sum can be >100 if there is more than 1 core but this property maxes out at 100. So, as long as the sum of all this process's threads is less than 100 you can get your answer by dividing the process's PercentProcessorTime property by the core count of the machine.

如果要从Win32_PerfFormattedData_PerfProc_Process获取此值,可以使用问题中提到的查询。这将为您提供所有此进程的线程的PercentProcessorTime值的总和。问题是,如果有超过1个核心,此总和可以大于100但是此属性最大值为100.因此,只要所有此进程的线程之和小于100,您就可以通过划分进程来获得答案PercentProcessorTime属性由计算机的核心计数。

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).

如果要在PowerShell中从PerfMon获取此值,可以使用Get-Counter“\ Process(SqlServr)\%Processor Time”。这将返回0 - (CoreCount * 100)之间的数字。

If you want to calculate this value for yourself the PercentProcessorTime property on the Win32_PerfRawData_PerfProc_Process provider returns the CPU time this process has used. So, you'll need to take two snapshots we'll call them s1 and s2. We'll then do (s2.PercentProcessorTime - s1.PercentProcessorTime) / (s2.TimeStamp_Sys100NS - s1.TimeStamp_Sys100NS).

如果要自己计算此值,Win32_PerfRawData_PerfProc_Process提供程序上的PercentProcessorTime属性将返回此进程使用的CPU时间。所以,你需要拍两张我们称之为s1和s2的快照。然后我们将(s2.PercentProcessorTime - s1.PercentProcessorTime)/(s2.TimeStamp_Sys100NS - s1.TimeStamp_Sys100NS)。

And that is the final word. Hope it helps you.

这是最后一句话。希望它能帮到你。

#2


5  

Your hypothesis is almost correct. A single thread (and a process will always have at least one thread) can have at most 100% for PercentProcessorTime but:

你的假设几乎是正确的。对于PercentProcessorTime,单个线程(以及进程总是至少有一个线程)最多可以有100%但是:

  • A process can have multiple threads.
  • 一个进程可以有多个线程。
  • A system can have multiple (logical) CPU cores.
  • 系统可以具有多个(逻辑)CPU核心。

Hence here (Intel i7 CPU with hyperthreading on) I have 8 logical cores, and the top 20 threads (filtering out totals) shows (with a little tidying up to make it readable):

因此在这里(带有超线程的Intel i7 CPU)我有8个逻辑核心,前20个线程(过滤总数)显示(稍微整理以使其可读):

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 add up to something like 800 for the last column.

所有这些都应该加起来为最后一列的800。

But note this is all rounded to integers. Compare with the CPU column of Process Explorer (which doesn't round when View | Show Fractional CPU is selected) over a few processes. Note, much like win32_PerfFormattedData_PerfProc_Process the percentage value is normalised for the core count (and this is only part of the display):

但请注意,这四舍五入到整数。与Process Explorer的CPU列(在选择View | Show Fractional CPU时不会舍入)比较几个进程。注意,就像win32_PerfFormattedData_PerfProc_Process一样,百分比值针对核心计数进行了标准化(这只是显示的一部分):

A lot of processes are using a few hundreds of thousands of cycles, but not enough to round up to a single percent.

很多流程都使用了几十万个周期,但还不足以将其整合到一个百分点。

如何使用PowerShell监视进程的CPU利用率?

#3


0  

Have you tryed Get-Counter ?

你试过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 depend on you locale test :

请注意,这取决于您的区域设置测试:

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

#1


9  

Everything I've learned about WMI and performance counters over the last couple of days.

我在过去几天里所学到的关于WMI和性能计数器的一切。

WMI stands for Windows Management Instrumentation. WMI is a collection of classes registered with 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 queried.

WMI代表Windows Management Instrumentation。 WMI是使用WMI系统和Windows COM子系统注册的类的集合。这些类称为提供程序,具有任意数量的公共属性,可在查询时返回动态数据。

Windows comes pre-installed with a large number of WMI providers that give you information about the Windows environment. For this question we are concerned with the Win32_PerfRawData* providers and the two wrappers that build off of it.

Windows预安装了大量WMI提供程序,可为您提供有关Windows环境的信息。对于这个问题,我们关注的是Win32_PerfRawData *提供程序以及构建它的两个包装器。

If you query any Win32_PerfRawData* provider directly you'll notice the numbers it returns are scary looking. That's because these providers give the raw data you can use to calculate whatever you want.

如果您直接查询任何Win32_PerfRawData *提供程序,您会注意到它返回的数字是可怕的。那是因为这些提供商提供了原始数据,您可以用它来计算您想要的任何数据。

To make it easier to work with the Win32_PerfRawData* providers Microsoft has provided two wrappers that return nicer answers when queried, PerfMon and Win32_PerfFormattedData* providers.

为了更容易使用Win32_PerfRawData *提供程序,Microsoft提供了两个包装器,在查询时返回更好的答案,PerfMon和Win32_PerfFormattedData *提供程序。

Ok, so how do we get a process's % CPU utilization? We have three options:

好的,那么我们如何获得进程的%CPU利用率?我们有三种选择:

  1. Get a nicely formatted number from the Win32_PerfFormattedData_PerfProc_Process provider
  2. 从Win32_PerfFormattedData_PerfProc_Process提供程序获取格式良好的数字
  3. Get a nicely formatted number from PerfMon
  4. 从PerfMon获取格式良好的数字
  5. Calculate the % CPU utilization for ourselves using Win32_PerfRawData_PerfProc_Process
  6. 使用Win32_PerfRawData_PerfProc_Process计算自己的%CPU利用率

We will see that there is a bug with option 1 so that it doesn't work in all cases even though this is the answer usually given on the internet.

我们将看到选项1存在错误,因此它在所有情况下都不起作用,即使这是通常在互联网上给出的答案。

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 this process's threads. The problem is that this sum can be >100 if there is more than 1 core but this property maxes out at 100. So, as long as the sum of all this process's threads is less than 100 you can get your answer by dividing the process's PercentProcessorTime property by the core count of the machine.

如果要从Win32_PerfFormattedData_PerfProc_Process获取此值,可以使用问题中提到的查询。这将为您提供所有此进程的线程的PercentProcessorTime值的总和。问题是,如果有超过1个核心,此总和可以大于100但是此属性最大值为100.因此,只要所有此进程的线程之和小于100,您就可以通过划分进程来获得答案PercentProcessorTime属性由计算机的核心计数。

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).

如果要在PowerShell中从PerfMon获取此值,可以使用Get-Counter“\ Process(SqlServr)\%Processor Time”。这将返回0 - (CoreCount * 100)之间的数字。

If you want to calculate this value for yourself the PercentProcessorTime property on the Win32_PerfRawData_PerfProc_Process provider returns the CPU time this process has used. So, you'll need to take two snapshots we'll call them s1 and s2. We'll then do (s2.PercentProcessorTime - s1.PercentProcessorTime) / (s2.TimeStamp_Sys100NS - s1.TimeStamp_Sys100NS).

如果要自己计算此值,Win32_PerfRawData_PerfProc_Process提供程序上的PercentProcessorTime属性将返回此进程使用的CPU时间。所以,你需要拍两张我们称之为s1和s2的快照。然后我们将(s2.PercentProcessorTime - s1.PercentProcessorTime)/(s2.TimeStamp_Sys100NS - s1.TimeStamp_Sys100NS)。

And that is the final word. Hope it helps you.

这是最后一句话。希望它能帮到你。

#2


5  

Your hypothesis is almost correct. A single thread (and a process will always have at least one thread) can have at most 100% for PercentProcessorTime but:

你的假设几乎是正确的。对于PercentProcessorTime,单个线程(以及进程总是至少有一个线程)最多可以有100%但是:

  • A process can have multiple threads.
  • 一个进程可以有多个线程。
  • A system can have multiple (logical) CPU cores.
  • 系统可以具有多个(逻辑)CPU核心。

Hence here (Intel i7 CPU with hyperthreading on) I have 8 logical cores, and the top 20 threads (filtering out totals) shows (with a little tidying up to make it readable):

因此在这里(带有超线程的Intel i7 CPU)我有8个逻辑核心,前20个线程(过滤总数)显示(稍微整理以使其可读):

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 add up to something like 800 for the last column.

所有这些都应该加起来为最后一列的800。

But note this is all rounded to integers. Compare with the CPU column of Process Explorer (which doesn't round when View | Show Fractional CPU is selected) over a few processes. Note, much like win32_PerfFormattedData_PerfProc_Process the percentage value is normalised for the core count (and this is only part of the display):

但请注意,这四舍五入到整数。与Process Explorer的CPU列(在选择View | Show Fractional CPU时不会舍入)比较几个进程。注意,就像win32_PerfFormattedData_PerfProc_Process一样,百分比值针对核心计数进行了标准化(这只是显示的一部分):

A lot of processes are using a few hundreds of thousands of cycles, but not enough to round up to a single percent.

很多流程都使用了几十万个周期,但还不足以将其整合到一个百分点。

如何使用PowerShell监视进程的CPU利用率?

#3


0  

Have you tryed Get-Counter ?

你试过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 depend on you locale test :

请注意,这取决于您的区域设置测试:

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