Top e ps não mostram o mesmo resultado da CPU

54

Isso está vinculado a esta pergunta.

Quando corro top, obtenho o seguinte resultado:

insira a descrição da imagem aqui

O pid 3038está usando 18% da CPU, no entanto, ao executar

insira a descrição da imagem aqui

o resultado é de 5,5%. E esse número não parece estar mudando com o tempo (ou seja, ao executar o mesmo comando um pouco mais tarde) ...

O pscomando está de alguma forma calculando a média do uso da CPU?

Theodor
fonte

Respostas:

87

man psna NOTESseção.

   CPU usage is currently expressed as the percentage of time spent running
   during the entire lifetime of a process.  This is not ideal, and it does not
   conform to the standards that ps otherwise conforms to.  CPU usage is
   unlikely to add up to exactly 100%.

E, suponha que você saiba, mas você também pode:

top -p <PID>

Editar : quanto ao seu comentário em outra resposta;

" Hmm, sim, gostaria de saber como obter isso (a porcentagem instantânea de CPU) do ps "

Resposta curta: você não pode.

Por que é tão?

É como pedir a alguém que calcule a velocidade de um carro a partir de uma foto.

Enquanto topé uma ferramenta de monitoramento, psé uma ferramenta de captura instantânea. Pense assim: a qualquer momento, um processo usa a CPU ou não. Assim, você tem 0% ou 100% de carga naquele momento exato.

Dando: Se psdeveria fornecer uso instantâneo da CPU , seria 0% ou 100%.

top por outro lado, mantenha os números das pesquisas e calcule a carga ao longo do tempo.

pspoderia ter fornecido o uso atual - mas isso exigiria a leitura de dados várias vezes e a suspensão entre cada leitura. Não faz.

Cálculo para ps% cpu

ps calcula o uso da CPU da seguinte maneira:

tempo de atividade = tempo total do sistema em execução.
ps_time = hora de início do processo medida em segundos a partir da inicialização.
pu_time = tempo total em que o processo está usando a CPU.

;; Segundos em execução:
segundos = tempo de atividade - ps_time
;; Uso:
cpu_usage = pu_time * 1000 / segundos

impressão: cpu_usage / 10 "." cpu_usage% 10


Exemplo: tempo de atividade = 344.545 ps_time = 322.462 pu_time = 3.383 segundos = 344.545 - 322.462 = 22.083 cpu_usage = 3.383 * 1.000 / 22.083 = 153 impressão: 153/10 "." 153% 10 => 15,3

Portanto, o número impresso é: o tempo em que o processo está usando a CPU durante sua vida útil. Como no exemplo acima. Isso foi feito em 15,3% de sua vida útil. Em 84,7% do tempo, não estava ocorrendo erros no CPU.

Recuperação de dados

ps, além de topusar dados de arquivos armazenados em /proc/- ou no sistema de pseudo-arquivos de informações do processo .

Você tem alguns arquivos na raiz /proc/que contêm várias informações sobre o estado geral do sistema. Além disso, cada processo tem sua própria subpasta /proc/<PID>/onde dados específicos do processo são armazenados. Por exemplo, o processo da sua pergunta tinha uma pasta em /proc/3038/.

Quando pscalcula o uso da CPU, ele usa dois arquivos:

/ proc / uptime O tempo de atividade do sistema (segundos) e a quantidade de tempo gasto no processo inativo (segundos).
/ proc / [PID] / stat Informações de status sobre o processo.
  • A partir uptimedele, usa o primeiro valor ( tempo de atividade ).
  • Dela [PID]/statusa o seguinte:
 # Nome Descrição
14 utime de tempo de CPU gasto no código do usuário, medido em instantes
15 stime de tempo de CPU gasto no código do kernel, medido em instantes
16 horas de CPU gastas em código de usuário, incluindo tempo de crianças
17 horas da CPU gastas no código do kernel, incluindo o tempo das crianças 
22 hora de início Hora em que o processo começou, medido em instantes

Um instante é o relógio. Portanto, além disso, ele usa vários métodos, por exemplo sysconf(_SC_CLK_TCK), para obter o Hertz do sistema (número de ticks por segundo) - usando 100 como retorno, depois de esgotar outras opções.

Então, se utimeé 1234 e Hertz é 100, então:

seconds = utime / Hertz = 1234 / 100 = 12.34

O cálculo real é feito por:

total_time = utime + stime

IF include_dead_children
    total_time = total_time + cutime + cstime
ENDIF

seconds = uptime - starttime / Hertz

pcpu = (total_time * 1000 / Hertz) / seconds

print: "%CPU" pcpu / 10 "." pcpu % 10

Exemplo (Saída de um script Bash personalizado):

$ ./psw2 30894
System information
           uptime : 353,512 seconds
             idle : 0
Process information
              PID : 30894
         filename : plugin-containe
            utime : 421,951 jiffies 4,219 seconds
            stime : 63,334 jiffies 633 seconds
           cutime : 0 jiffies 0 seconds
           cstime : 1 jiffies 0 seconds
        starttime : 32,246,240 jiffies 322,462 seconds

Process run time  : 31,050
Process CPU time  : 485,286 jiffies 4,852 seconds
CPU usage since birth: 15.6%

Cálculo da carga "atual" com ps

Este é um (pouco?) Esforço obscuro, mas está bem. Vamos tentar.

Pode-se usar os tempos fornecidos por pse calcular o uso da CPU a partir disso. Ao pensar sobre isso, poderia realmente ser bastante útil, com algumas limitações.

Isso pode ser útil para calcular o uso da CPU por um período mais longo. Ou seja, você deseja monitorar a carga média da CPU plugin-containerno Firefox enquanto executa alguma tarefa relacionada ao Firefox.

Usando a saída de:

$ ps -p -o cputime, etimes

CODE    HEADER   DESCRIPTION
cputime TIME     cumulative CPU time, "[DD-]hh:mm:ss" format.  (alias time).
etime   ELAPSED  elapsed time since the process was started, [DD-]hh:]mm:ss.
etimes  ELAPSED  elapsed time since the process was started, in seconds.

Uso etimemais etimesnesta amostra, nos cálculos, apenas para ser um pouco mais claro. Também adiciono% cpu por "diversão". Em um script bash, obviamente, alguém usaria etimes- ou melhor, leria /proc/<PID>/etc.

Start:
$ ps -p 30894 -o %cpu,cputime,etime,etimes
%CPU     TIME     ELAPSED ELAPSED
 5.9 00:13:55    03:53:56   14036

End:
%CPU     TIME     ELAPSED ELAPSED
 6.2 00:14:45    03:56:07   14167

Calculate times:
            13 * 60 + 55 =    835   (cputime this far)
3 * 3,600 + 53 * 60 + 56 = 14,036   (time running this far)

            14 * 60 + 45 =    885   (cputime at end)
3 * 3,600 + 56 * 60 +  7 = 14,167   (time running at end)

Calculate percent load:
((885 - 835) / (14,167 - 14,036)) * 100 = 38

O processo estava usando a CPU 38% do tempo durante esse período.

Veja o código

Se você quiser saber como psé que é, e conhecer um pouco de C, faça (parece que você roda o Gnome Debain deriavnt) - boa atitude no código em relação aos comentários, etc .:

apt-get source procps
cd procps*/ps
vim HACKING
Runium
fonte
Eu posso atualizar com mais informações tope monitoramento contínuo - ou ajustar com atraso, também conhecido como " ps" com a carga atual da CPU.
Runium
2
Realmente ótima resposta!
Theodor
Que tal ao calcular o uso total da CPU em todo o sistema. As ferramentas estão tentando obter o uso da CPU por meio de um instantâneo ou calculando a média ao longo do tempo?
CMCDragonkai
4
man top

%CPU  --  CPU usage
The  task's share of the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time.  In a true SMP environment, if 'Irix
mode' is Off, top will operate in 'Solaris mode' where a task's cpu usage will be divided by the total number of CPUs.  You toggle  'Irix/Solaris'  modes
with the 'I' interactive command.


man ps 
%cpu       %CPU    cpu utilization of the process in "##.#" format. Currently, it is the CPU time used divided by the time the process has been running                       (cputime/realtime ratio), expressed as a percentage. It will not add up to 100% unless you are lucky. (alias pcpu).
Rahul Patil
fonte
Hmm, sim eu me pergunto como conseguir que (a porcentagem CPU instantânea) deps
Theodor
2
você pode extrair do exemplo principaltop -p 3343 -n1 | awk '/ R /{print $10}'
Rahul Patil
11
Impressionante. Eu descobri que awk: para o pidmelhor funcionou, como emtop -p 3343 -n1 | awk '/ 3343 /{print $10}'
Theodor
11
Obrigado "top -p" é legal, eu nunca notei essa opção! No entanto, eu não gosto de procurar o PID, e se por acaso os mesmos dígitos aparecerem na seção de memória livre ou algo assim. No meu sistema a informação está na linha 8 e 9 de coluna, portanto, eu faço:top -p $PID -n1 | awk '{if (NR ==8) print $9 }'
phil_w