【问题标题】:How to get total CPU Idle Time in Objective C/C on OS X?如何在 OS X 上的 Objective C/C 中获取总 CPU 空闲时间?
【发布时间】:2013-12-09 13:32:56
【问题描述】:

我需要在 OS X 上的 Objective C/C 中获取总 CPU 空闲时间?

如果可能,请提供执行此操作的代码示例。 这是我用来获取这些指标的代码。结果百分比与我在活动监视器中的百分比不同。所以我假设 CPU 时间计算不正确:

#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);
}

【问题讨论】:

标签: objective-c c macos cpu-usage


【解决方案1】:

默认情况下,从进程计量器或顶部返回的值是基于样本增量的,即它们计算自上一个样本以来的 CPU 使用率,而不是绝对值。

这对应于在模式中调用时选项-c n to top:

 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(&amp;deltasample) 时,它会打印增量记录,该记录提供的值与 topActivity 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];
}

【讨论】:

  • 我需要获取活动监视器(CPU)中显示的值。您能否提供一个代码示例或解决方案来修复我上面已经提供的代码。提前谢谢你。
  • 我已经用一种方法更新了我的答案,以更准确地表示活动监视器中显示的值。
  • 请记住,还有一个CPU_STATE_NICE,为了计算,它被计为用户时间的一部分。
  • 我不知道实现,但这些值应该来自引导。不断增加似乎是正确的行为;当然,除非我们实际上看到了价值的环绕(这似乎不太可能)
  • 这个数学是正确的——记住你的 totalSystemTime 是在所有内核上累积的(即除以 8 以获得 8 核系统);然而,当 _SC_CLK_TCK == 100 时,使用纳秒表示该值是在声称该值的准确性是错误的。
猜你喜欢
  • 2011-04-02
  • 1970-01-01
  • 2011-09-23
  • 2013-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
  • 1970-01-01
相关资源
最近更新 更多