Как отслеживать использование ЦП процесса с помощью PowerShell?

Я пытаюсь написать сценарий PowerShell для мониторинга использования % CPU процесса SQL Server. Я хотел бы записывать снимки этого числа каждый день, чтобы мы могли отслеживать его с течением времени и следить за тенденциями.

мои исследования в интернете сказали, что этот запрос WMI должен дать мне то, что я хочу:

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

когда я запускаю запрос WMI, я обычно получаю значение где-то между 30-50% enter image description here

однако, когда я наблюдаю за процессом в Resource Monitor, он обычно усредняется на менее 1% использования ЦП SQL Server Average CPU Utilization

Я знаю, что запрос WMI просто возвращает снимок использования ЦП, а не среднее значение в течение длительного периода времени, поэтому я знаю, что они напрямую не сопоставимы. Тем не менее, я думаю, что снимок обычно должен быть меньше 1%, так как среднее значение монитора ресурсов меньше 1%.

3 ответов


все, что я узнал о WMI и счетчиках производительности за последние пару дней.

WMI означает инструментарий управления Windows. WMI-это набор классов, зарегистрированных в системе WMI и подсистеме Windows COM. Эти классы известны как поставщики и имеют любое количество открытых свойств, возвращающих динамические данные при запросе.

Windows поставляется с предустановленным большим количеством поставщиков WMI, которые дают вам информацию о среда Windows. Для этого вопроса нас интересует Win32_PerfRawData* поставщики и две обертки, которые строятся из него.

при запросе любой Win32_PerfRawData* провайдер сразу вы заметите, что цифры его возвращение страшно смотреть. Это потому, что эти поставщики дают необработанные данные, которые вы можете использовать для вычисления того, что вы хотите.

чтобы упростить работу с поставщиками Win32_PerfRawData * Microsoft предоставила две оболочки, которые возвращайте более приятные ответы при запросе, perfmon и win32_perfformatteddata* провайдеров.

Ok, Итак, как мы получаем % загрузки процессора процесса? У нас есть три варианта:

  1. получите красиво отформатированный номер от поставщика Win32_PerfFormattedData_PerfProc_process
  2. получить красиво отформатированный номер от PerfMon
  3. рассчитать % загрузки процессора для себя с помощью Win32_PerfRawData_PerfProc_Process

мы увидим что есть ошибка с вариантом 1, так что он не работает во всех случаях, хотя это ответ, обычно данный в интернете.

Если вы хотите получить это значение из Win32_PerfFormattedData_PerfProc_process вы можете использовать запрос, упомянутый в вопросе. Это даст вам сумму значения PercentProcessorTime для всех потоков этого процесса. Проблема в том, что эта сумма может быть >100, если существует более 1 ядра, но это свойство максимизируется на 100. Так, покуда сумма всех потоков этого процесса меньше 100 вы можете получить ответ, разделив свойство percentprocessortime процесса на количество ядер машины.

Если вы хотите получить это значение от PerfMon в PowerShell, вы можете использовать Get-Counter "\Process(SqlServr)\% Processor Time". Это вернет число между 0 - (CoreCount * 100).

Если вы хотите вычислить это значение для себя, свойство PercentProcessorTime поставщика Win32_PerfRawData_PerfProc_Process возвращает время процессора это процесс использовал. Итак, вам нужно сделать два снимка, мы назовем их s1 и s2. Затем мы сделаем (s2.PercentProcessorTime-s1.PercentProcessorTime) / (s2.TimeStamp_Sys100NS-s1.TimeStamp_Sys100NS).

и это последнее слово. Надеюсь, это вам поможет.


ваша гипотеза почти верна. Один нить (и процесс всегда будет иметь хотя бы один поток) может иметь не более 100% для PercentProcessorTime но:

  • процесс может иметь несколько потоков.
  • система может иметь несколько (логических) ядра процессора.

следовательно, здесь (процессор Intel i7 с hyperthreading on) у меня есть 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 для последнего столбца.

но обратите внимание, что все это округлено до целых чисел. Сравните со столбцом CPU Process Explorer (который не округляется, когда выбран просмотр | отображение дробного процессора) в течение нескольких процессов. Обратите внимание, как win32_PerfFormattedData_PerfProc_Process процентное значение нормализуется для основного количества (и это только часть дисплея):

много процессов через несколько сотен тысяч циклов, но не настолько, чтобы округлить до одного процента.

enter image description here


ты пробовал 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

будьте осторожны, это зависит от вас locale test:

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