Что нового

Узнаём нагруженность ЦП конкретным процессом

lightforever

Новичок
Сообщения
37
Репутация
2
Как программно узнать насколько сильно грузит в текущий момент конкретный процесс ЦП?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Сначала немного теории. Полное время работы любого просесса складывается из следующих составляющих:

Код:
$iTimeProc = $iTimeKernelProc + $iTimeUserProc + $iTimeIdleProc


Время работы просессора определяется аналогичным образом:

Код:
$iTimeCPU = $iTimeKernelCPU + $iTimeUserCPU + $iTimeIdleCPU


где

$iTimeKernel... - время работы в Kernel режиме
$iTimeUser... - время работы в User режиме
$iTimeIdle... - время бездействия

Для вычисления загрузки CPU определенным процессом нам понадобятся первые два параметра - $iTimeKernel... и $iTimeUser... Тогда загрузку CPU в % за определенный промежуток времени (dt = t2 - t1) можно посчитать по следующей формуле:

Код:
$iUsage = (($iTimeKernelProc2 + $iTimeUserProc2) - ($iTimeKernelProc1 + $iTimeUserProc1)) / (($iTimeKernelCPU2 + $iTimeUserCPU2) - ($iTimeKernelCPU1 + $iTimeUserCPU1)) * 100


$iTimeKernelProc и $iTimeUserProc возвращает функция _WinAPI_GetProcessTimes(), а $iTimeKernelCPU и $iTimeUserCPU - _WinAPI_GetSystemTimes() (см. документацию).

Вот простой пример для одного процесса:

Код:
#Include <GUIListView.au3>
#Include <ListViewConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPIEx.au3>

Global Const $sProcess = 'firefox.exe'

Global $hListView, $PID = 0, $Prev1 = 0, $Prev2 = 0

GUICreate('MyGUI', 384, 200, -1, -1, -1, $WS_EX_TOPMOST)
GUICtrlCreateListView('| | | ', 10, 10, 364, 180, BitOR($LVS_DEFAULT, $LVS_NOSORTHEADER), $WS_EX_CLIENTEDGE)
$hListView = GUICtrlGetHandle(-1)
_GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_INFOTIP))
_GUICtrlListView_SetColumn($hListView, 0, 'Process', 140)
_GUICtrlListView_SetColumn($hListView, 1, 'PID', 52)
_GUICtrlListView_SetColumn($hListView, 2, 'CPU, %', 52, 1)
_GUICtrlListView_SetColumn($hListView, 3, 'Memory', 74, 1)
GUISetState()

_Update()

AdlibRegister('_Update', 500)

Do
Until GUIGetMsg() = -3

Func _Update()

	Local $ID, $Mem, $Time1, $Time2

	$ID = ProcessExists($sProcess)
	If $ID Then
		$Time1 = _WinAPI_GetProcessTimes($ID)
		$Time2 = _WinAPI_GetSystemTimes()
		If (IsArray($Time1)) And (IsArray($Time2)) Then
			$Time1 = $Time1[1] + $Time1[2]
			$Time2 = $Time2[1] + $Time2[2]
			If ($Prev1) And ($Prev2) And ($PID = $ID) Then
				$Mem = _WinAPI_GetProcessMemoryInfo($PID)
				If Not _GUICtrlListView_GetItemCount($hListView) Then
					_GUICtrlListView_AddItem($hListView, '')
					_GUICtrlListView_AddSubItem($hListView, 0, '', 1)
					_GUICtrlListView_AddSubItem($hListView, 0, '', 2)
					_GUICtrlListView_AddSubItem($hListView, 0, '', 3)
				EndIf
				_SetText(_WinAPI_GetProcessName($PID), 0)
				_SetText($PID, 1)
				_SetText(Round(($Time1 - $Prev1) / ($Time2 - $Prev2) * 100), 2)
				_SetText(_KB(Round($Mem[9] / 1024)), 3)
			EndIf
			$Prev1 = $Time1
			$Prev2 = $Time2
			$PID = $ID
			Return
		EndIf
	EndIf
	If _GUICtrlListView_GetItemCount($hListView) Then
		_GUICtrlListView_DeleteAllItems($hListView)
	EndIf
	$Prev1 = 0
	$Prev2 = 0
	$PID = 0
EndFunc   ;==>_Update

Func _KB($iSize)
	If StringLen($iSize) > 3 Then
		Return StringTrimRight($iSize, 3) & ',' & StringLeft($iSize, 3) & ' K'
	EndIf
EndFunc   ;==>_KB

Func _SetText($sText, $iIndex)
	If StringCompare(_GUICtrlListView_GetItemText($hListView, 0, $iIndex), $sText, 1) Then
		_GUICtrlListView_SetItemText($hListView, 0, $sText, $iIndex)
	EndIf
EndFunc   ;==>_SetText


Для запуска этого скрипта, тебе понадобится последняя версия библиотеки WinAPIEx.
 

mechlab

Новичок
Сообщения
19
Репутация
0
Доброго:smile:
Извиняюсь.. а как узнать тотальную загрузку процессора?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
$iUsageCPU = ($iTimeKernelCPU + $iTimeUserCPU) / ($iTimeKernelCPU + $iTimeUserCPU + $iTimeIdleCPU) * 100
 

erlik

Продвинутый
Сообщения
317
Репутация
84
Yashied
Твоя функция (надеюсь не против, что обращаюсь на ты?) _WinAPI_GetProcessMemoryInfo в массиве под индексом 9 возвращает размер памяти процесса совпадающей с данными Диспетчера задач в колонке "вирт. память". То есть отнюдь не размер ее текущего использования.
А как же получить именно размер RAM используемой процессом в текущей момент?
PS: Что странно - колонка данных "вирт.память" при этом не совпадает с данными возвращаемыми свойством VirtualSize класса Win32_Process (WMI).
 

mechlab

Новичок
Сообщения
19
Репутация
0
Код:
#Include <GUIListView.au3>
#Include <ListViewConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPIEx.au3>

        $Time1 = _WinAPI_GetProcessTimes()
        $Time2 = _WinAPI_GetSystemTimes()
$iTimeKernelProc  = $Time1 [1]
;~   MsgBox(0,"$iTimeKernelProc",$iTimeKernelProc)
$iTimeUserProc = $Time1 [2]
;~   MsgBox(0,"$iTimeUserProc",$iTimeUserProc )

;~ $iTimeIdle = $Time1 [3]
;~ MsgBox(0,"$iTimeIdle",$iTimeIdle)

$iTimeKernelCPU = $Time2 [1]
;~   MsgBox(0,"$iTimeKernelCPU",$iTimeKernelCPU)
$iTimeUserCPU = $Time2 [2]
;~   MsgBox(0,"$iTimeUserCPU",$iTimeUserCPU)
$iTimeIdleCPU = $Time2 [0]


$iUsage = (($iTimeKernelProc + $iTimeUserProc)  / ($iTimeKernelCPU + $iTimeUserCPU + $iTimeIdleCPU )) * 100

  MsgBox(0,"$iTimeUserCPU",$iUsage)


Вот так вот? :-[


Добавлено:
Сообщение автоматически объединено:

Нет.. что то у мне я не получается... запутался с возвращаемыми значениями функций
Код:
_WinAPI_GetProcessTimes() _WinAPI_GetSystemTimes()



Добавлено:
Сообщение автоматически объединено:

Код:
$iUsage = ($iTimeKernelCPU + $iTimeUserCPU ) / ($iTimeKernelCPU + $iTimeUserCPU + $iTimeIdleCPU) * 100

так у меня стабильно выдает 51,84... хотя загрузка по диспетчеру 7-11%
 

VladUs

Скриптер
Сообщения
621
Репутация
181
erlik [?]
А как же получить именно размер RAM используемой процессом в текущей момент?
Может так:
Узнаем текущюю память занятую процессом calc.exe
Код:
$strComputer = "." 
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2") 
$colItems = $objWMIService.ExecQuery( "SELECT * FROM Win32_PerfFormattedData_PerfProc_Process WHERE Name = 'Calc'") 
For $objItem in $colItems 
    ConsoleWrite ("Память занятая процессам в данный момент: " & $objItem.WorkingSet  /1024 & " кб" & @Cr)
Next
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
#Include <WinAPIEx.au3>

Global $Time1 = 0, $Time2 = 0

GUICreate('MyGUI', 400, 400)
GUICtrlCreateLabel('CPU usage:', 20, 20, 58, 14)
$Label = GUICtrlCreateLabel('0%', 80, 20, 40, 14)
GUISetState()

AdlibRegister('_CPU', 1000)

Do
Until GUIGetMsg() = -3

Func _CPU()

	Local $Time2 = _WinAPI_GetSystemTimes()

	If IsArray($Time1) Then
		$TimeBusyCPU = ($Time2[1] + $Time2[2]) - ($Time1[1] + $Time1[2])
		$TimeIdleCPU = ($Time2[0] - $Time1[0])
		GUICtrlSetData($Label, StringFormat('%.f%', ($TimeBusyCPU - $TimeIdleCPU) / $TimeBusyCPU * 100))
	EndIf
	$Time1 = $Time2
EndFunc   ;==>_CPU
 

zlaya_kisa

Новичок
Сообщения
5
Репутация
0
как можно определить загрузку каждого ядра процессом,а не общую загрузку?
 
Верх