Como é calculada a utilização do CPU?
na minha área de trabalho, tenho um pequeno elemento que me diz a minha utilização actual da CPU. Também mostra o uso para cada um dos meus dois núcleos.
sempre me perguntei, como é que a CPU calcula a quantidade da sua potência de processamento que está a ser usada? Além disso, se a CPU está presa fazendo alguns cálculos intensos, como ela (ou o que quer que lida com esta atividade) examinar o uso, sem ficar presa também?
8 answers
A CPU não faz os cálculos de utilização por si só. Ele pode ter recursos de hardware para tornar essa tarefa mais fácil, mas é principalmente o trabalho do sistema operacional. Assim, obviamente, os detalhes das implementações vão variar (especialmente no caso dos sistemas multicores).
A ideia geral é ver quanto tempo é a fila de coisas que a CPU precisa de fazer. O sistema operacional pode dar uma olhada no scheduler periodicamente para determinar o número de coisas que ele tem que fazer.
Isto é uma função Linux em (extraída da Wikipédia) que executa esse cálculo:
#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_FREQ (5*HZ) /* 5 sec intervals */
#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */
#define EXP_5 2014 /* 1/exp(5sec/5min) */
#define EXP_15 2037 /* 1/exp(5sec/15min) */
#define CALC_LOAD(load,exp,n) \
load *= exp; \
load += n*(FIXED_1-exp); \
load >>= FSHIFT;
unsigned long avenrun[3];
static inline void calc_load(unsigned long ticks)
{
unsigned long active_tasks; /* fixed-point */
static int count = LOAD_FREQ;
count -= ticks;
if (count < 0) {
count += LOAD_FREQ;
active_tasks = count_active_tasks();
CALC_LOAD(avenrun[0], EXP_1, active_tasks);
CALC_LOAD(avenrun[1], EXP_5, active_tasks);
CALC_LOAD(avenrun[2], EXP_15, active_tasks);
}
}
Quanto à segunda parte da sua pergunta, os sistemas operativos mais modernos são multifuncionais. Isso significa que o SO não vai permitir que os programas ocupem todo o tempo de processamento e não tenham nenhum para si (a menos que você faça isso). Em outras palavras, mesmo que uma aplicação pareça pendurada, o SO podeainda roubar algum tempo para o seu próprio trabalho.
Há uma tarefa especial chamada a tarefa ociosa que corre quando nenhuma outra tarefa pode ser executada. O % de uso é apenas a porcentagem do Tempo em que não estamos executando a tarefa ociosa. O sistema operacional manterá um total de execução do tempo gasto a executar a tarefa ociosa:
- Quando mudarmos para a tarefa ociosa, Definir t = tempo actual
- Quando mudarmos para longe da tarefa ociosa, Adicione (Tempo actual-t) ao total de execução
Para obter a utilização do CPU, amostrar periodicamente oTotal tempo do processo, e encontrar a diferença.
Por exemplo, se estes são os tempos da CPU para o processo 1:
kernel: 1:00:00.0000
user: 9:00:00.0000
E depois obtê - los novamente dois segundos depois, e eles são:
kernel: 1:00:00.0300
user: 9:00:00.6100
Você subtrai os tempos de kernel (para uma diferença de 0.03
) e os tempos de utilizador (0.61
), adiciona-os juntos (0.64
), e divide pelo tempo de amostra de 2 segundos (0.32
).
As chamadas específicas do sistema necessárias para obter esta informação são (obviamente) diferentes em todas as plataformas. No Windows, poderá usar Getprocessvezes , ou Getsystemvezes se quiser um atalho para total usado ou tempo de CPU inactivo.
Uma maneira de o fazer é a seguinte:
Escolha um intervalo de amostragem, digamos a cada 5 minutos (300 segundos) do tempo real decorrido. Você pode obter isso de {[[0]}.
Arranja o tempo de processo que usaste nesses 300 segundos. Você pode usar a chamadatimes()
para obter isso. Esse seria o new_process_time - old_process_time
, onde old_process_time
é o tempo de processo que você salvou do último intervalo de tempo.
A sua percentagem de cpu é então (process_time/elapsed_time)*100.0
Você pode definir um alarme para sinalizar a cada 300 segundos para fazer estes cálculos.
Pode encontrar-se um código de exemplo fixe no sítio web do MSDNs que mostra as chamadas de funções para calcular a utilização do CPU para um conjunto de instruções: http://msdn.microsoft.com/en-us/library/aa364157 (VS.85).aspx
O que estas chamadas do sistema fazem é aceder ao código do kernel, creio eu... o que está além do alcance da minha compreensão.
Há uma série de maneiras de o fazer:
O processador mantém vários contadores que medem o desempenho, você pode acessá-los usando a interface Papi. por exemplo, aqui está uma breve introdução: http://blogs.oracle.com/jonh/entry/performance_counter_generic_events
Também: http://www.drdobbs.com/tools/184406109
O contador que poderá querer é o PAPI_TOT_CYC, que é o número de ciclos de ocupado (se bem me lembro)
while(true){}
Repete que o sistema operativo gira para cima. Seu processo é gerenciado a partir desse loop. Ele permite que o código externo seja executado diretamente no processador em pedaços. Sem exagerar demasiado, trata-se de uma simplificação uber do que está realmente a acontecer.
A CPU não fica "pendurada", está simplesmente operando na capacidade de pico, o que significa que está processando tantas instruções quanto é fisicamente capaz a cada segundo. O processo que está calculando o uso de CPU é algumas dessas instruções. Se as aplicações tentarem fazer operações mais rápido do que o CPU é capaz, então simplesmente elas serão atrasadas, daí o 'hang up'.
O cálculo da utilização da CPU baseia-se na utilização total disponível. Por isso, se uma CPU tiver dois núcleos, e um núcleo tem 30% de uso, e o outro 60%, a utilização global é de 45%. Você também pode ver o uso de cada núcleo individual.