Здраствуйте.
Подскажите пожалуйста каким образом в Win2K/Xp узнать загруженость процессора конкретным процессом. Например, как в диспечере задач Windows.
GetProcessTimes не советовать, т.к. он возвращает время старта и т.д а мне надо загруженность процессора в процентах.
Заранее спасибо.
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
20-12-2007 08:06 | Комментарий к предыдущим ответам
Следует еще поделить на 10000, чтобы получить в миллисекундах.
А зачем? Я же предложил использовать GetSystemTimeAsFileTime вместо GetTickCount (или что там автор использовал), в этом случае никакие лишние преобразования не требуются, просто два вычитания и деление. Нам ведь по сути не интересны единицы измерения времени, мы всё равно хотим получить только отношение "времени работы" к "прошедшему времени".
12-12-2007 10:01 | Комментарий к предыдущим ответам
А чем не устраивает Pdh.dll?
В данном случае это что "гланды автогеном удалять", никому не нужное усложнение, к тому же я уверен, что Performance Counters будут использовать всё тот же GetProcessTimes.
Вот как следует преобразовывать _FILETIME в миллисекунды:
Проще так:
CurrentKernelTime := Int64(lpKernelTime);
А вот так делать не стоит:
Result := (CurrentTime - FSaveTime) * 100 / Timer1.Interval;
потому что таймеры очень не стабильны и при сильной загрузке у вас будут совсем не те числа, что вы ожидаете. Лучше сохранять и CurrentTime и реальное время (GetSystemTimeAsFileTime), а в формуле использовать разницу между реальным и запомненным.
// в глобальных переменных (или как поле формы):
var
FSaveTime: Extended;
function GetProcessPerf: Double;
var
lpCreationTime, lpExitTime, lpKernelTime, lpUserTime: _FILETIME;
CurrentTime: Extended;
begin
Result := 0;
GetProcessTimes(GetCurrentProcess, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
// Получаем текущее время как время работы процесса в режиме ядра и в режиме пользователя
CurrentTime := (Int64(lpKernelTime.dwHighDateTime shl 32) + lpKernelTime.dwLowDateTime) / 10000;
CurrentTime := CurrentTime + (Int64(lpUserTime.dwHighDateTime shl 32) + lpUserTime.dwLowDateTime) / 10000;
if (FSaveTime <> 0) then // если первый вызов, то пропускаем
Result := (CurrentTime - FSaveTime) * 100 / Timer1.Interval;
FSaveTime := CurrentTime;
end;
Ну и можно усреднить по количеству процессоров, если это необходимо.
Здраствуйте.
Сделал как вы написали, все нормально показывает, но загруженность процессора у меня отображается примерно в 2 раза больше чем на самом деле.
Тут я задумался и понял :-) ,что у меня включен Hyper-Threading, т.е. 2 процессора и надо делить на 2 (с отключенным Hyper-Threading все соответствовало).
Вопрос: Как узнать включен Hyper-Threading или нет.
Заранее спасибо.
Вас не интересуют возвращаемые lpCreationTime, lpExitTime, а только lpKernelTime, lpUserTime. Здесь, дубликат инкремента для уменьшения погрешности при переходе ч/з нуль.
Далее, в любом таймере, например TTimer ежесекундно (!) считываем значение CurrentTime и отнимаем его от сохранённого дифференциала на предыдущем этапе и делим на 10 (т.к. % есть значение делённое на 1000 (привязка по оси X к текущему времени), умноженное на 100):
procedure TForm.TimerTimer(Sender: TObject);
var
FlashTime: Integer;
GetProcessTimes возвращает чистое время затраченное системой на выполнение процесса (там два времени, но мы их просуммируем). Вызываем GetProcessTimes положим раз в секунду, запоминаем предыдущее время, вычитаем из текущего, делим на секунду, вот вам и загрузка в процентах.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.