Как получить общее время простоя процессора в Objective C/C на OS X?
Мне нужно получить общее время простоя процессора в Objective C/C на OS X?
Если возможно, приведите пример кода, который делает это. Вот код, который я использую, чтобы получить эти метрики. Как результат, процент не такой, как у меня в Activity Monitor. Таким образом, я предполагаю, что вычисление времени процессора неверно:
#include <sys/sysctl.h>
#include <sys/types.h>
#include <mach/mach.h>
#include <mach/processor_info.h>
#include <mach/mach_host.h>
- (void)printCPUUsage
{
processor_cpu_load_info_t cpuLoad;
mach_msg_type_number_t processorMsgCount;
natural_t processorCount;
uint64_t totalSystemTime = 0, totalUserTime = 0, totalIdleTime = 0, totalCPUTime = 0;
kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &processorCount, (processor_info_array_t *)&cpuLoad, &processorMsgCount);
for (natural_t i = 0; i < processorCount; i++) {
// Calc load types and totals, with guards against 32-bit overflow
// (values are natural_t)
uint64_t system = 0, user = 0, idle = 0, total = 0;
system = cpuLoad[i].cpu_ticks[CPU_STATE_SYSTEM];
user = cpuLoad[i].cpu_ticks[CPU_STATE_USER];
idle = cpuLoad[i].cpu_ticks[CPU_STATE_IDLE];
total = system + user + idle;
if (total < 1) {
total = 1;
}
totalCPUTime += total;
totalSystemTime += system;
totalUserTime += user;
totalIdleTime += idle;
}
double onePercent = totalCPUTime/100.0f;
NSLog(@"system: %f", (double)totalSystemTime/(double)onePercent);
NSLog(@"user: %f", (double)totalUserTime/(double)onePercent);
NSLog(@"idle: %f", (double)totalIdleTime/(double)onePercent);
}
1 ответ
Значения, возвращаемые измерителем процесса или верхом, по умолчанию основаны на дельте выборки, т.е. они рассчитывают загрузку ЦП со времени предыдущей выборки, а не абсолютные значения.
Это соответствует варианту -c n
наверх при вызове в режиме:
top -c n -l 0 | head -5
Какой режим по умолчанию. Если вы хотите, чтобы значения возвращались в вашем коде, тогда вам нужно основывать значения на непосредственных примерах, используя:
top -c e -l 0 | head -5
Эти значения будут соответствовать значениям, которые вы видите.
Если вы хотите получить аналогичные значения для измерителя / верха процесса, вам нужно взять две выборки и отобразить значения различий между ними.
Так, например, мы создаем структуру, содержащую статистику:
struct cpusample {
uint64_t totalSystemTime;
uint64_t totalUserTime;
uint64_t totalIdleTime;
};
мы изменяем вызов printCPUUsage, чтобы он выполнял пример:
void sample(struct cpusample *sample)
{
processor_cpu_load_info_t cpuLoad;
mach_msg_type_number_t processorMsgCount;
natural_t processorCount;
uint64_t totalSystemTime = 0, totalUserTime = 0, totalIdleTime = 0;
kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &processorCount, (processor_info_array_t *)&cpuLoad, &processorMsgCount);
for (natural_t i = 0; i < processorCount; i++) {
// Calc load types and totals, with guards against 32-bit overflow
// (values are natural_t)
uint64_t system = 0, user = 0, idle = 0;
system = cpuLoad[i].cpu_ticks[CPU_STATE_SYSTEM];
user = cpuLoad[i].cpu_ticks[CPU_STATE_USER] + cpuLoad[i].cpu_ticks[CPU_STATE_NICE];
idle = cpuLoad[i].cpu_ticks[CPU_STATE_IDLE];
totalSystemTime += system;
totalUserTime += user;
totalIdleTime += idle;
}
sample->totalSystemTime = totalSystemTime;
sample->totalUserTime = totalUserTime;
sample->totalIdleTime = totalIdleTime;
}
Затем мы берем два образца (1 секунда между образцами):
struct cpusample delta;
sample(&sample1);
sleep(1);
sample(&sample2);
deltasample.totalSystemTime = sample2.totalSystemTime - sample1.totalSystemTime;
deltasample.totalUserTime = sample2.totalUserTime - sample1.totalUserTime;
deltasample.totalIdleTime = sample2.totalIdleTime - sample1.totalIdleTime;
Добавить распечатанный код:
void printSample(struct cpusample *sample)
{
uint64_t total = sample->totalSystemTime + sample->totalUserTime + sample->totalIdleTime;
double onePercent = total/100.0f;
NSLog(@"system: %f", (double)sample->totalSystemTime/(double)onePercent);
NSLog(@"user: %f", (double)sample->totalUserTime/(double)onePercent);
NSLog(@"idle: %f", (double)sample->totalIdleTime/(double)onePercent);
}
поэтому, когда вы вызываете printSample(&deltasample)
он печатает дельта-запись, которая дает гораздо более похожую ценность на ту, что представлена top
или же Activity Monitor
,
Но если честно, я бы использовал host_statistics
, так как код чище:
void sample(struct cpusample *sample)
{
kern_return_t kr;
mach_msg_type_number_t count;
host_cpu_load_info_data_t r_load;
uint64_t totalSystemTime = 0, totalUserTime = 0, totalIdleTime = 0;
count = HOST_CPU_LOAD_INFO_COUNT;
kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (int *)&r_load, &count);
if (kr != KERN_SUCCESS) {
printf("oops: %s\n", mach_error_string(kr));
return;
}
sample->totalSystemTime = r_load.cpu_ticks[CPU_STATE_SYSTEM];
sample->totalUserTime = r_load.cpu_ticks[CPU_STATE_USER] + r_load.cpu_ticks[CPU_STATE_NICE];
sample->totalIdleTime = r_load.cpu_ticks[CPU_STATE_IDLE];
}