12

我正在尝试编写一个 PowerShell 脚本来监视 SQL Server 进程的 CPU 利用率百分比。我想每天记录这个数字的快照,这样我们就可以随着时间的推移对其进行监控并观察趋势。

我的在线研究说这个 WMI 查询应该给我我想要的:

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

当我运行 WMI 查询时,我通常会得到一个介于 30-50% 之间的值 在此处输入图像描述

但是,当我在资源监视器中查看进程时,它的 CPU 使用率通常低于 1% SQL Server 平均 CPU 利用率

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

有人对为什么会有如此大的差异有任何想法吗?以及如何准确测量进程的 CPU 使用率?

4

3 回答 3

16

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

WMI 代表 Windows 管理规范。WMI 是向 WMI 系统和 Windows COM 子系统注册的类的集合。这些类称为提供者,并具有任意数量的公共属性,这些属性在查询时会返回动态数据。

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

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

为了更轻松地使用 Win32_PerfRawData* 提供程序,Microsoft 提供了两个包装器,它们在查询时会返回更好的答案,即 PerfMon 和 Win32_PerfFormattedData* 提供程序。

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

  1. 从 Win32_PerfFormattedData_PerfProc_Process 提供程序获取格式良好的数字
  2. 从 PerfMon 获取格式正确的数字
  3. 使用 Win32_PerfRawData_PerfProc_Process 为我们自己计算 % CPU 使用率

我们将看到选项 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.

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

如果您想自己计算此值,Win32_PerfRawData_PerfProc_Process 提供程序上的 PercentProcessorTime 属性将返回此进程已使用的 CPU 时间。因此,您需要拍摄两个快照,我们将它们称为 s1 和 s2。然后我们将执行 (s2.PercentProcessorTime - s1.PercentProcessorTime) / (s2.TimeStamp_Sys100NS - s1.TimeStamp_Sys100NS)。

这是最后的话。希望它可以帮助你。

于 2012-07-19T16:59:49.493 回答
7

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

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

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

PS > gwmi Win32_PerfFormattedData_PerfProc_Thread |
    ?{$_.Name -notmatch '_Total'} |
    排序 PercentProcessorTime -desc |
    选择-前 20 |
    ft -auto Name,IDProcess,IDThread,PercentProcessorTime

名称 IDProcess IDThread PercentProcessorTime
---- --------- -------- --------
空闲/6 0 0 100
空闲/3 0 0 100
空闲/5 0 0 100
空闲/1 0 0 100
空闲/7 0 0 96
空闲/4 0 0 96
空闲/0 0 0 86
空闲/2 0 0 68
WmiPrvSE/7#1 7420 6548 43
dwm/4 2260 6776 7
mstsc/2#1 3444 2416 3
电源外壳/7#2 6352 6552 0
主机/0#2 6360 6368 0
电源外壳/5#2 6352 6416 0
电源外壳/6#2 6352 6420 0
iexplore/7#1 4560 3300 0
福昕阅读器/1 736 5304 0
福昕阅读器/2 736 6252 0
主机/1#2 6360 1508 0
福昕阅读器/0 736 6164 0

对于最后一列,所有这些加起来应该是 800 之类的东西。

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

许多流程使用了几十万个周期,但不足以四舍五入到百分之一。

在此处输入图像描述

于 2012-07-18T14:52:50.717 回答
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"}
于 2012-07-17T20:43:20.657 回答