Как получить значение загрузки CPU в % конкретным процессом

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Как получить значение загрузки CPU в % конкретным процессом

Сообщение Vova_2581 » 26.06.2019 (Ср) 11:04

Здравствуйте!
Знаю - избитая тема, но тем не менее, есть вопросы. В общем, суть проблемы: есть процесс... нужно получить динамические данные, в реальном времени, загрузки CPU этим процессом в % выражении.

Что было сделано...
В первую очередь, решил пойти простым и доступным путем: использовать технологию WMI. Выполнить запрос класса Win32_PerfFormattedData_PerfProc_Process, передать ему PID нужного процесса и через функцию PercentProcessorTime получить нужные данные.
Типа вот так...
Код: Выделить всё
Private Sub Form_Load()
Set PIDItems = GetObject("winmgmts:\\.\root\CIMV2").ExecQuery("SELECT * FROM Win32_PerfFormattedData_PerfProc_Process where IDProcess=" & "здесь указываем PID нужного процесса", , 48)
  For Each objItem In PIDItems
  Debug.Print objItem.PercentProcessorTime
  Next
End Sub

Такой код работает, и можно даже заключить его в цикл... но проблема в том, что вызвав стандартный «Диспетчер задач» и сравнив поле «ЦП»... с данным кодом, выявилось, что показания двух приложений относительно одного и того же процесса получаются совершенно разные. WMI показывает: 70... 0... 20... 100... а Диспетчер задач Windows показывает: 09... 2... 12... 36... 24... и т.д.

Шаг второй...
На этом почтенном форуме, нашел похожую тему и пример кода от пользователя jangle вот здесь...
http://bbs.vbstreets.ru/viewtopic.php?p=6675693&sid=05c636f4ed851d7bc1936b8c23190f13#p6675693
jangle написал Native DLL на PowerBasic, в которой использует API – GetProcessTimes, получая разницу последних двух ее аргументов, тем самым вычисляет эти самые %. Казалось бы: бери и пользуйся! Но... дальнейшие испытания кода от jangle немного смутили, пришлось снова плакать в подушку. :cry: Вот по какой причине... Я взял не Блокнот, а видеоплейер, что у меня есть – PotPlayerMini, запустил на нем фильм, и получил тоже самое, что и с кодом WMI... Даже еще хуже! Показания не редко уходили за 100%, чего быть вроде как не должно!
Посмотрите скриншоты...
Безымянный 1.jpg
Безымянный 1.jpg (85.24 Кб) Просмотров: 5424

Безымянный 4.jpg

Безымянный 5.jpg

Безымянный 6.jpg

В связи с чем вопрос: может Диспетчер задач отображает в «ЦП» что-то другое??? Но вроде как нет... Как мне тогда получить реальные данные загрузки CPU по типу, как отображает стандартный Диспетчер задач???
Разъясните, пожалуйста, поподробней.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение jangle » 26.06.2019 (Ср) 16:34

Посмотрел этот древний код, скорее всего ошибка в этой строке

Код: Выделить всё
  Ret = (ValUFTDiff + ValKFTDiff) \ 50000


наверное надо

Код: Выделить всё
  Ret = (ValUFTDiff + ValKFTDiff) \ 500000     

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение alibek » 26.06.2019 (Ср) 17:38

И еще следует учитывать, что утилизация CPU в процентах интуитивна, но некорректна.
Это не мгновенное значение, а изменение.
Lasciate ogni speranza, voi ch'entrate.

bon818
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 267
Зарегистрирован: 29.08.2009 (Сб) 4:49
Откуда: Ташкент

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение bon818 » 26.06.2019 (Ср) 18:53

Похоже, что «Диспетчер задач» в поле «ЦП» показывает среднее значение за секунду.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 27.06.2019 (Чт) 10:17

Здравствуйте, jangle!
jangle писал(а):Посмотрел этот древний код, скорее всего ошибка в этой строке...

По всей видимости число 50000 или 500000 есть числом произвольным, как я понимаю??? Некий коэффициент... С Вашего позволения, я пошел дальше... взял не видеоплейер, а (так чтоб наверняка грузануть проц.) архиватор WinRAR и стал на нем архивировать фильм. Таким образом загрузил проц. (у меня 1 ядро) почти полностью. Далее немного подправил Ваш код вот так...
Код: Выделить всё
Ret = (ValUFTDiff + ValKFTDiff) \ 200000

Компилировал новую DLL и получил вот такой результат...

Res3.jpg
Res3.jpg (74.74 Кб) Просмотров: 5374

Res2.jpg
Res2.jpg (75.9 Кб) Просмотров: 5374

Res1.jpg
Res1.jpg (78.1 Кб) Просмотров: 5374

Это уже ближе к реальности. :) Теперь мне подушка почти не нужна... :D
Есть правда один досадный момент (не успел уловить скриншотами), но все же иногда мельком (очень быстро) ненамного, но значения все-таки выходят за 100% . Где-то так, примерно: 106... 103... 110... и т.д.
Очевидно присутствие баг в строке библиотеки...
Код: Выделить всё
IF Ret < 0 THEN Ret = 0 : IF Ret > 100 THEN Ret = 100

Не пойму: почему несмотря на ограничения, некорректные значения все же проскакивают??? :(
alibek писал(а):И еще следует учитывать, что утилизация CPU в процентах интуитивна, но некорректна.
Это не мгновенное значение, а изменение.

Ок. Учтем.
bon818 писал(а):«Диспетчер задач» в поле «ЦП» показывает среднее значение за секунду

То есть Вы имеете ввиду, если я правильно Вас понял, что ДЗ делает ну, скажем, 10 замеров в секунду, а потом вычисляет среднее и выводит, как результат в поле "ЦП"???

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 27.06.2019 (Чт) 10:34

Vova_2581 писал(а):Очевидно присутствие баг в строке библиотеки...
IF Ret < 0 THEN Ret = 0 : IF Ret > 100 THEN Ret = 100

Кажется исправилось... Просто убрал :
И написал в две строки...
Код: Выделить всё
IF Ret < 0 THEN Ret = 0
IF Ret > 100 THEN Ret = 100

Теперь выход за 100% не наблюдается. :) Подушку вообще выкинул! Ура! :D

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 27.06.2019 (Чт) 10:48

Вот сам улучшенный проект, попробуйте поэкспериментировать, если есть желание...
Вложения
CPU_Usage improved.rar
(5.74 Кб) Скачиваний: 176

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 01.07.2019 (Пн) 9:51

Вчера снова плакал в подушку. Старую то я выкинул, пришлось купить новую. :cry: Она уже вся мокрая! :(
Рано обрадовался. В общем, вынужден констатировать факт: библиотека от jangle работает некорректно. Число делителя в формуле: Ret = (ValUFTDiff + ValKFTDiff) \ 200000 библиотеки напрямую зависит от платформы на которой запущена программа с DLL. Речь идет о количестве физических ядер CPU. На одноядерном компе одни числа %, на двуядерном - другие, а на четырехядерном - третьи. Получается так, что число делителя должно быть переменным в зависимости от ядер CPU! Посмотрите скриншоты...

Это 1 ядерный CPU... При делителе 200000...
Test1.jpg
Test1.jpg (118.7 Кб) Просмотров: 5321

Это 2 ядерный CPU... Тот же делитель...
Test1.jpg
Test1.jpg (86.74 Кб) Просмотров: 5321

Это 4 ядерный CPU... При все том же делителе...
Test.jpg

Test2.jpg


Так что вопрос по прежнему остается открытым. :roll: Миллион тому, кто даст правильный ответ!

Teranas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 224
Зарегистрирован: 13.12.2008 (Сб) 4:26
Откуда: Новосибирск

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Teranas » 01.07.2019 (Пн) 10:01

Подушку можно высушить на солнышке.
А значения брать из реестра, там есть всё и общее значение и для каждого ядра.
Когда я делал индикатор ЦП, я брал значения там.
На днях поищу тебе исходник, если нужен, конечно.
С уважением, Андрей.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 01.07.2019 (Пн) 10:11

Teranas
Очень нужен! Если есть то пожалуйста... :) Только есть важный момент! И он кроется в названии этого топика...
Нужно не общее значение загрузки CPU, а для конкретного процесса. Такое в реестре тоже есть???

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 01.07.2019 (Пн) 19:13

Есть идея! Кое что подправил в DLL... нужно провести новые испытания. Завтра напишу...
Teranas
Но Вы мне свой код все равно скиньте, пожалуйста, мне интересно... :roll:

Teranas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 224
Зарегистрирован: 13.12.2008 (Сб) 4:26
Откуда: Новосибирск

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Teranas » 02.07.2019 (Вт) 7:47

Если для каждого процесса, то

NTAPI получить можно через NtQuerySystemInformation
или
WinAPI - GetProcessTimes и GetSystemTimes

Процент CPU может быть представлен формулой: числитель сумма lpUserTime и lpKernelTime из GetProcessTimes, знаменатель представленный суммой из тех же значений, но из GetSystemTimes, - частное умножается на 100.

Для NtQuerySystemInformation, но код не мой.
Код: Выделить всё
Declare Function NtQuerySystemInformation Lib "ntdll.dll" (dwInfoType As DWord,lpStructure As VoidPtr,dwSize As DWord,dwReserved As DWord) As DWord

Type SYSTEM_PERFORMANCE_INFORMATION

    IdleTime As LARGE_INTEGER
    KernelTime As LARGE_INTEGER
    UserTime As LARGE_INTEGER
    Reserved1[2] As LARGE_INTEGER
    Reserved2 As LARGE_INTEGER

End Type

Dim OldSPI As SYSTEM_PERFORMANCE_INFORMATION
Dim SPI As SYSTEM_PERFORMANCE_INFORMATION
Dim OldUserTime As QWord
Dim OldKernelTime As QWord
Dim OldIdleTime As QWord
Dim UserTime As QWord
Dim KernelTime As QWord
Dim IdleTime As QWord
Dim ResultUserTime As QWord
Dim ResultKernelTime As QWord
Dim ResultIdleTime As QWord
Dim ResultSystemTime As QWord
Dim CPUUsage As QWord
Dim Message[256] As Byte

Do

    NtQuerySystemInformation(8,VarPtr(OldSPI),Len(OldSPI),NULL)
    Sleep(1000)
    NtQuerySystemInformation(8,VarPtr(SPI),Len(SPI),NULL)
    memcpy(VarPtr(OldUserTime),VarPtr(OldSPI.UserTime),8)
    memcpy(VarPtr(OldKernelTime),VarPtr(OldSPI.KernelTime),8)
    memcpy(VarPtr(OldIdleTime),VarPtr(OldSPI.IdleTime),8)
    memcpy(VarPtr(UserTime),VarPtr(SPI.UserTime),8)
    memcpy(VarPtr(KernelTime),VarPtr(SPI.KernelTime),8)
    memcpy(VarPtr(IdleTime),VarPtr(SPI.IdleTime),8)
    ResultUserTime=OldUserTime-UserTime
    ResultKernelTime=OldKernelTime-KernelTime
    ResultIdleTime=OldIdleTime-IdleTime
    ResultSystemTime=ResultUserTime+ResultKernelTime
    CPUUsage=(ResultSystemTime-ResultIdleTime)*100/ResultSystemTime
    lstrcpy(Message,"CPU ???: ")
    lstrcat(Message,Str$(CPUUsage))
    lstrcat(Message," %")
    SetWindowText(_PromptSys_hWnd,Message)

Loop
С уважением, Андрей.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение alibek » 02.07.2019 (Вт) 10:54

Vova_2581 писал(а):Нужно не общее значение загрузки CPU, а для конкретного процесса

Не бывает моментального значения «общее значение загрузки CPU».
Нужно брать интегральное (суммарное) значение процессорного времени процесса за определенный период и делить его на общее процессорное время (время периода × количество ядер/сокетов).
Lasciate ogni speranza, voi ch'entrate.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 02.07.2019 (Вт) 11:10

C этим NtQuerySystemInformation довольно запутанно... В качестве аргумента, нужно передавать указатель на структуру VarPtr(OldSPI), через секунду получать новые значения со все той же структуры, но в SYSTEM_PERFORMANCE_INFORMATION не указывается идентификатор на конкретный интересующий нас процесс. Или этого потом нужно отлавливать по результатам работы этой функции из общей кучи полученных результатов?? Потом еще работа с памятью... И дальнейшие вычисления... похоже, что этот код показывает только общую загрузку CPU, но не отдельного процесса.
Я решил пока поработать с функцией GetProcessTimes- с ней полегче, к тому же есть уже готовый код от jangle. За что ему большое спасибо!
Только немного модифицировал DLL. Пока испытания проходят успешно, но еще не закончены. Мне тут нужно договариваться с разными людьми у которых компы с большим количеством ядер CPU. А это непросто!
Есть у меня один знакомый - человек сложный и замкнутый, и таким он стал, после того, как купил себе 8-ми(!) ядерный комп. При встрече всегда спрашивает: "ты кто такой?? Иди от сюда!.." :(
Сделал себе татуировку своего 8-ми ядерного процессора на всю грудь со словами "I love Intel" на латыни с золотыми куполами и иконами. Ни с кем не здоровается, и все время ходит с растопыренными пальцами в виде буквы "W".
Короче, крутой пацик! Он у нас один на селе! Мне нужно будет с ним как-то договориться - проверить прогу на его компе, но пока не знаю, как к нему подойти, чтобы не обделаться от сурового нахмуренного взгляда.
Сделаю попытку... если получится остаться в живых, то напишу о результатах.
alibek
Ну это теория, нужно думать над практикой... чем я сейчас и занимаюсь.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение alibek » 02.07.2019 (Вт) 14:28

cpu.png
cpu.png (67.22 Кб) Просмотров: 5261
Lasciate ogni speranza, voi ch'entrate.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 03.07.2019 (Ср) 9:35

12 ядер!!! :shock: Ни хууу...хрена себе!!! :silent: :shock:
alibek, Я Вас уважаю!! Получается, что и у Вас тоже тату проца на всю грудь???!! :scratch:

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 03.07.2019 (Ср) 9:44

Блин... что-то я ваще запутался... по описанию на Ваш проц. E5-2695 физических вроде 12-ть, а по картинке... логических так аж целых 48! ОГО! :shock:
Что-то дурно мне... воздуха не хватает... мне нужно выйти... отдышаться... :pale:

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 03.07.2019 (Ср) 10:37

Фух... немного отдышался. Корвалол - делает чудеса!
Я понял... у Вас на материнке аж два(!) CPU по 12 ядер каждая! Да еще и эмуляция их до 48! Ну это... просто... вообще... :shock:

У меня к Вам просьба... пока еще не потерял сознание...
Вы не могли бы запустить у себя на этом компе вот эту утилиту... не волнуйтесь это не зловред, можете проверить сами. Это просто результат работы API, которая собирает данные о процессоре. Меня в данном случае интересует последнее в этом списке значение... Какое она покажет число CPU у Вас. Это важно! Пожалуйста...
Вложения
CPUinfo.rar
(3.2 Кб) Скачиваний: 176
Последний раз редактировалось Vova_2581 04.07.2019 (Чт) 9:01, всего редактировалось 1 раз.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение alibek » 03.07.2019 (Ср) 12:44

Vova_2581 писал(а):Да еще и эмуляция их до 48

Это называется не эмуляция, а гипертрединг.

Vova_2581 писал(а):Вы не могли бы запустить у себя на этом компе вот эту утилиту...

Разумеется нет. Это не мой личный ПК, а сервер в production.
Lasciate ogni speranza, voi ch'entrate.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 04.07.2019 (Чт) 9:24

Эх, жаль... :( Было бы любопытно, что показала бы утилита с учетом этого гипер... как Вы там сказали. Ну, да ладно, переживем.
Значит, у меня получилось договорится с этим крутым пациком... на нашем селе, но когда я ему сказал про Ваш 48-ми ядерный комп. Он не поверил и вообще разозлился сильно! Кричал, что круче него нет никого на этом свете! А потом схватил топор... дальше не знаю, не видел... потому что бежал очень быстро, даже не помню, как перелетел через забор в три метра, но(!) главное не это, а то, что я успел сохранить все результаты на флешке и в ближайшее время опубликую.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 05.07.2019 (Пт) 10:17

Итак, результаты...
Вот скриншоты проведенных испытаний на разных платформах, операционных системах и набором ядер CPU...

1 ядерный CPU... Windows XP
Test 1 Win XP.jpg
Test 1 Win XP.jpg (124.18 Кб) Просмотров: 5162

2 ядерный CPU... Windows XP
Test 2 WinXP.jpg
Test 2 WinXP.jpg (129.71 Кб) Просмотров: 5162

2 ядерный CPU... Windows 7
Test 3 Win7.jpg
Test 3 Win7.jpg (138.74 Кб) Просмотров: 5162

4 ядерный CPU... Windows XP
Test 4 WinXP.jpg
Test 4 WinXP.jpg (141.05 Кб) Просмотров: 5162

8 ядерный CPU... Windows 10
Test 5 Win10.jpg

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 05.07.2019 (Пт) 10:18

8 ядерный CPU... Windows 10
Test 6 Win10.jpg

Как видите... результаты одинаковые. Теперь все совпадает... как и должно быть.
Последний раз редактировалось Vova_2581 05.07.2019 (Пт) 10:28, всего редактировалось 1 раз.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 05.07.2019 (Пт) 10:25

А вот, что показывает утилита CPUInfo на 8-ми ядернике...
CPU info.jpg
CPU info.jpg (29.32 Кб) Просмотров: 5162

Последний пункт в списке показывает количество ядер. Мне было важно знать какое значение покажет утилита на машине с гипертредингом CPU, потому что на основе этого строится поправка DLL. Будет ли это значение physical processor или logical processor??? Остальное напишу позже, поскольку все не помещается в один пост...

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 05.07.2019 (Пт) 10:51

Ну, а теперь самое главное...
Для того, чтобы все работало как надо, пришлось немного изменить логику финальной формулы вычислений в библиотеке от jangle. А именно статический делитель заменен на динамический в зависимости от количества ядер в системе. Небольшие изменения, но главное, что теперь все работает. Вот сейчас сижу и думаю: порвать мне подушку или просто выкинуть??? :scratch: Как Вы считаете?? :wink:
Вложения
CPU_Usage correction DLL.rar
(5.89 Кб) Скачиваний: 195

Vova_2581
Постоялец
Постоялец
 
Сообщения: 376
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: Как получить значение загрузки CPU в % конкретным процес

Сообщение Vova_2581 » 07.07.2019 (Вс) 7:40

Ну, если вопросов ни у кого не осталось... стало быть, тему можно считать закрытой.
Спасибо всем участникам! :)


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex-бот и гости: 32

    TopList  
cron