Como obter a porcentagem de CPU como contador?

2

Gostaria de monitorar a porcentagem total de utilização da CPU como um contador. A razão pela qual eu gostaria que ele fosse um contador é que os dados não serão perdidos entre as amostras (e eu posso ter o lado gráfico para calcular a taxa).

Minha abordagem inicial foi usar /proc/uptime com a fórmula (uptime-(idle_time/num_core))*100 . Isso geralmente parece ser preciso em um grande número de servidores (algo como 98% do tempo), mas às vezes pareço ter resultados errados. Por exemplo, o seguinte parece sugerir que houve uso negativo da CPU, o que não faz muito sentido:

[root@ny-lb05 ~]# echo -e "scale=10\n ($(cut -f1 -d' ' /proc/uptime)-($(cut -f2 -d' ' /proc/uptime)/16))*100" | bc
5646895.3750000000
[root@ny-lb05 ~]# echo -e "scale=10\n ($(cut -f1 -d' ' /proc/uptime)-($(cut -f2 -d' ' /proc/uptime)/16))*100" | bc
5646891.5625000000

Neste servidor estou em execução:

Linux ny-lb05.ds.stackexchange.com 2.6.32-431.11.2.el6.x86_64 #1 SMP Tue Mar 25 19:59:55 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

Alguém vê um erro nesse método de cálculo? Existe uma maneira melhor de obter a utilização da CPU como um contador?

Atualização:
Então, o que eu estou procurando é o tempo total de utilização como um contador crescente monotônico. Espero que a utilização total nunca diminua . Mas esse parece ser o caso com o seguinte: [root@ny-lb05 ~]# read uptime idle </proc/uptime; echo -e "scale=1000\n ($uptime*16-($idle))" | bc 903874.23 [root@ny-lb05 ~]# read uptime idle </proc/uptime; echo -e "scale=1000\n ($uptime*16-($idle))" | bc 903870.29

Além disso, de acordo com / proc / cpuinfo, núcleos = irmãos, então acredito que o HT não está ativado.

Atualização 2:
TLDR; / proc / uptime está com problemas, use / proc / stat.

    
por Kyle Brandt 09.04.2014 / 14:15

2 respostas

4

(uptime-(idle_time/num_core))

Pode dar uma ideia de há quanto tempo o sistema está ocupado, em segundos. A multiplicação por 100 faz com que seja centésimos de segundos - essa é a sua intenção?

IMO faria mais sentido considerar quantos segundos do processador estavam disponíveis e subtrair o tempo ocioso daquele:

uptime * num_core - idle_time = total active processor seconds

Uma métrica de utilização pode ser:

active seconds / (uptime * num_core)

Por exemplo, se o sistema estiver ativo por 10 segundos em 4 núcleos com 5 segundos de idle_time:

(10 * 4 - 5) / (10 * 4) = 0.875

87,5% de utilização.

Ou:

(10 - 5 / 4) / 10 = 0.875

A mesma coisa, salva uma operação.

Is there a better way to get CPU utilization as a counter?

Eu fiz isso em uma biblioteca C ++ de diagnóstico do sistema analisando a primeira linha de /proc/stat , que é um total combinado para todos os núcleos. Os três primeiros campos são hora do usuário, baixa prioridade (aka nice) e hora do sistema. O total destes é a quantidade de tempo ativo (note que a unidade aqui não é segundos, veja /proc/stat sob man proc ).

Se você fizer polling por mais de 5 segundos, assumindo um USER_HZ de 100, onde total_a é o primeiro exemplo (user + nice + sys) e total_b é o segundo exemplo:

(total_b - total_a) / 5 / 100 / num_cores = usage ratio

Se você multiplicar isso por 100, terá uma porcentagem indicando uma média no intervalo de 5 segundos.

Veja a lógica:

  • total_b - total_a = tempo ativo entre as amostras

  • Dividido pela duração da amostra, 5 segundos.

  • Dividido pelas unidades por segundo da medida (USER_HZ)

  • Dividido pelo número de núcleos

USER_HZ é quase certamente 100. Para verificar:

#include <stdio.h>
#include <unistd.h>

int main (void) {
    printf (
        "%ld\n", 
        sysconf(_SC_CLK_TCK)
    );

    return 0;
}

Compilação: gcc whatever.c , executar ./a.out .

Será difícil obter uma duração precisa para isso com ferramentas de shell, para que você possa manter uma medida crescente do tempo total de atividade (acho que é sua intenção) ou usar um intervalo bastante longo, por exemplo, 30+ segundos

    
por 09.04.2014 / 14:54
0

Seu problema provavelmente é porque você está lendo /proc/cputime de dois processos separados. O tempo ocioso aumentará ligeiramente entre cada cat , dando a possibilidade de uma leitura mais baixa na segunda vez. Eu recomendo fazer isso em vez disso:

read uptime idle </proc/cputime
echo -e "scale=10\n ($uptime-($idle/16))*100" | bc

Além disso, se você quiser que seus resultados sejam uma porcentagem total de utilização, você deve dividir o tempo de atividade novamente:

read uptime idle </proc/cputime
echo -e "scale=10\n ($uptime-($idle/16))/$uptime*100" | bc
    
por 09.04.2014 / 15:01