Как получить общее время простоя процессора в 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];
}
Другие вопросы по тегам