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

时间:2012-07-17 13:06:32

标签: sql-server powershell wmi

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

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

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

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

但是,当我在资源监视器中观察进程时,通常平均CPU使用率不到1% SQL Server Average CPU Utilization

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

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

3 个答案:

答案 0 :(得分:11)

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

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

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

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

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

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

  1. 从Win32_PerfFormattedData_PerfProc_Process提供程序中获取格式正确的数字
  2. 从PerfMon获取格式正确的数字
  3. 使用Win32_PerfRawData_PerfProc_Process计算自己的%CPU利用率
  4. 我们会看到选项1存在一个错误,因此它并不适用于所有情况,即使这是通常在互联网上给出的答案。

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

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

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

    这就是最后一句话。希望它可以帮到你。

答案 1 :(得分:7)

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

  • 进程可以有多个线程。
  • 系统可以有多个(逻辑)CPU核心。

因此在这里(带有超线程的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

所有这些都应该为最后一列添加800之类的东西。

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

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

enter image description here

答案 2 :(得分:0)

您是否尝试过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

小心取决于你的语言环境测试:

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