¿Cómo obtener el tiempo total de inactividad de la CPU en Objective C/C en OS X?

5 minutos de lectura

avatar de usuario
Sarga

¿Necesito obtener el tiempo total de inactividad de la CPU en Objective C/C en OS X?

Si es posible, proporcione un ejemplo de código que haga eso. Aquí hay un código que uso para obtener estas métricas. Como resultado, el porcentaje no es el mismo que tengo en el Monitor de actividad. Así que supongo que el cálculo del tiempo de CPU es incorrecto:

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

  • Eche un vistazo a – stackoverflow.com/questions/6785069/get-cpu-percent-usage. Eso calcula el uso total. Entonces, tiempo de inactividad = 100% – % de uso total

    –Anish Ramaswamy

    9 dic 2013 a las 15:46

  • En realidad, uso el mismo enfoque/código pero con una diferencia de cálculo entre las métricas actuales y anteriores.

    – Sergio

    9 de diciembre de 2013 a las 16:03

avatar de usuario
Petesh

Los valores que devuelve el medidor de proceso o la parte superior son, de manera predeterminada, basados ​​en delta de muestra, es decir, calculan el uso de la CPU desde la muestra anterior, en lugar de los valores absolutos.

Esto corresponde a la opción -c n to top cuando se llama en el modo:

 top -c n -l 0 | head -5

Cuál es el modo predeterminado. Si desea que los valores se devuelvan en su código, debe basar los valores en muestras inmediatas, usando:

 top -c e -l 0 | head -5

Estos valores se corresponderán con los valores que está viendo.

Si desea obtener valores similares al medidor/superior del proceso, debe tomar dos muestras y mostrar los valores de las diferencias entre ellas.

Entonces, por ejemplo, creamos una estructura que contiene las estadísticas:

struct cpusample {
    uint64_t totalSystemTime;
    uint64_t totalUserTime;
    uint64_t totalIdleTime;

};

modificamos la llamada printCPUUsage para que realice una muestra:

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

Luego tomamos dos muestras (1 segundo entre muestras):

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;

El agregar un código printsample:

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

así que cuando invoques printSample(&deltasample) imprime el registro delta, que da un valor mucho más similar al presentado por cualquiera top o Activity Monitor.

Pero para ser honesto, usaría host_statisticsya que el código es más limpio:

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];
}

  • Necesito obtener los valores que se muestran en el monitor de actividad (CPU). ¿Podría proporcionar una muestra de código que haga eso o una solución que arreglará mi código ya proporcionado anteriormente? Gracias de antemano.

    – Sergio

    9 de diciembre de 2013 a las 18:59


  • Actualicé mi respuesta con un método para representar con mayor precisión los valores que se muestran en el monitor de actividad.

    – Petesh

    9 de diciembre de 2013 a las 22:22

  • tenga en cuenta que también hay un CPU_STATE_NICEque se cuenta como parte del tiempo de usuario a efectos de cálculo.

    – Petesh

    9 de diciembre de 2013 a las 22:29

  • No estoy al tanto de la implementación, pero esos valores deberían ser desde el arranque. Incrementar continuamente parece un comportamiento correcto; a menos que, por supuesto, estemos viendo un ajuste en el valor (lo que parece poco probable)

    – Petesh

    10 de diciembre de 2013 a las 19:08


  • Esa matemática es correcta, teniendo en cuenta que su totalSystemTime se acumula en todos los núcleos (es decir, divídalo por 8 para un sistema de 8 núcleos); sin embargo, como _SC_CLK_TCK == 100, el uso de nanosegundos para el valor reclama una falsa sensación de precisión del valor.

    – Petesh

    10 de diciembre de 2013 a las 20:36

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad