Как получить тактовые частоты процессора, используемые процессом в режиме ядра на Windows?
Как следует из названия, я заинтересован в получении тактовых циклов процессора, используемых процессом только в режиме ядра. Я знаю, что есть API под названием "QueryProcessCycleTime", который возвращает тактовые циклы ЦП, используемые потоками процесса. Но это значение включает циклы, проведенные как в режиме пользователя, так и в режиме ядра. Как я могу получить циклы, проведенные только в режиме ядра? Нужно ли получать это с помощью счетчиков производительности? Если да, какой я должен использовать?
Заранее спасибо за ваши ответы.
2 ответа
Я только что нашел интересную статью, которая описывает почти то, что вы просите. Это на внутреннем устройстве MSDN.
Там пишут, что если бы вы использовали C# или C++/CLI, вы могли бы легко получить эту информацию из экземпляра System.Diagnostic.Process
класс, указал на правильный PID. Но это даст вам TimeSpan
от PrivilegedProcessorTime
так что "красивое время" вместо "циклов".
Тем не менее, они также указывают, что весь этот код.Net на самом деле является тонкой оболочкой для неуправляемых API, поэтому вы также сможете легко получить его из нативного C++. Они использовали ILDASM для показа того, что он называет, но изображение отсутствует. Я только что сделал то же самое, и он использует GetProcessTimes
от kernel32.dll
Итак, снова MSDN'ing это - он возвращает LPFILETIME
структур. Итак, снова "красивое время", а не "циклы".
Описание этого метода указывает на то, что если вы хотите получить тактовые циклы, вы должны использовать функцию QueryProcessCycleTime. Это на самом деле возвращает количество тактов... но пользовательский режим и режим ядра подсчитываются вместе.
Теперь подводим итоги:
- Вы можете прочитать userTIME
- вы можете прочитать kernelTIME
- Вы можете прочитать (пользователь + ядро) ЦИКЛЫ
Таким образом, у вас есть почти все необходимое. По простой математике:
u_cycles = u_time * allcycles / (utime+ktime)
k_cycles = k_time * allcycles / (utime+ktime)
Конечно, это будет некоторое приближение из-за округления и т. Д.
Кроме того, здесь есть недочёт: вам нужно вызвать две функции (GetTimes, QueryCycles), чтобы получить всю информацию, поэтому между их показаниями будет небольшая задержка, и, следовательно, все ваши вычисления , вероятно, будут немного проскальзывать, так как целевой процесс все еще бежит и сжигает время.
Если вы не можете учесть этот (небольшой?) Шум при измерении, я думаю, что вы можете обойти его, временно приостановив процесс:
- приостановить цель
- подождите немного и убедитесь, что он приостановлен
- читать первую статистику
- читать вторую статистику
- затем возобновите процесс и рассчитайте значения
Я думаю, что это обеспечит согласованность этих двух показаний, но, в свою очередь, каждое такое считывание будет влиять на общую производительность измеряемого процесса, то есть такие вещи, как "время стены", больше не будут измеряться, если вы не примете некоторые поправки для время, проведенное в подвешенном состоянии..
Может быть какой-то лучший способ получить отдельные тактовые циклы, но я их не нашел, извините. Вы можете попробовать заглянуть внутрь QueryProcessCycleTime
и из какого источника он читает данные - может быть, вам повезло, и он читает A,B и возвращает A+B, и, возможно, вы можете посмотреть, какие источники. Я не проверял это.
Взгляните на GetProcessTimes. Это даст вам количество ядра и пользовательское время, использованное вашим процессом.