Top y ps no muestran el mismo resultado de CPU

54

Esto está vinculado a esta pregunta.

Cuando corro topobtengo el siguiente resultado:

ingrese la descripción de la imagen aquí

pid 3038usa 18% de CPU, sin embargo, cuando se ejecuta

ingrese la descripción de la imagen aquí

El resultado es 5.5%. Y este número no parece estar cambiando con el tiempo (es decir, cuando se ejecuta el mismo comando un poco más tarde) ...

¿El pscomando promedia de alguna manera el uso de la CPU?

Theodor
fuente

Respuestas:

87

man psen la NOTESsección

   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%.

Y, supongo que lo sabes, pero también puedes hacer:

top -p <PID>

Editar : en cuanto a su comentario sobre otra respuesta;

" Hmm, sí, me pregunto cómo obtener eso (el porcentaje de CPU instantánea) de ps "

Respuesta corta: no puedes.

¿Por que es esto entonces?

Es como pedirle a alguien que calcule la velocidad de un automóvil a partir de una imagen.

Si bien topes una herramienta de monitoreo, pses una herramienta de instantánea. Piénselo así: en cualquier momento dado, un proceso usa la CPU o no. Por lo tanto, tiene 0% o 100% de carga en ese momento exacto.

Donaciones: si se psdebe dar un uso instantáneo de la CPU , sería 0% o 100%.

top por otro lado, mantenga los números de votación y calcule la carga a lo largo del tiempo.

pspodría haber dado el uso actual, pero eso requeriría que lea los datos varias veces y que duerma entre cada lectura. No lo hace.

Cálculo para ps% cpu

ps calcula el uso de la CPU de la siguiente manera:

tiempo de actividad = tiempo total que el sistema ha estado funcionando.
ps_time = tiempo de inicio del proceso medido en segundos desde el arranque.
pu_time = tiempo total que el proceso ha estado usando la CPU.

;; El proceso de segundos se ha estado ejecutando:
segundos = tiempo de actividad - ps_time
;; Uso:
cpu_usage = pu_time * 1000 / segundos

print: cpu_usage / 10 "." cpu_usage% 10


Ejemplo: tiempo de actividad = 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 impresión: 153/10 "." 153% 10 => 15,3

Entonces, el número impreso es: tiempo que el proceso ha estado usando la CPU durante su vida útil. Como en el ejemplo anterior. Lo ha hecho en el 15,3% de su vida útil. En el 84,7% del tiempo no ha estado molestando a la CPU.

Recuperación de datos

ps, así como top, utiliza datos de archivos almacenados en /proc/- o el sistema de pseudoarchivo de información de proceso .

Tiene algunos archivos en la raíz /proc/que tienen información diversa sobre el estado general del sistema. Además, cada proceso tiene su propia subcarpeta /proc/<PID>/donde se almacenan los datos específicos del proceso. Entonces, por ejemplo, el proceso de su pregunta tenía una carpeta en /proc/3038/.

Cuando pscalcula el uso de la CPU, utiliza dos archivos:

/ proc / uptime El tiempo de actividad del sistema (segundos) y la cantidad de tiempo dedicado al proceso inactivo (segundos).
/ proc / [PID] / stat Información de estado sobre el proceso.
  • A partir de uptimeél utiliza el primer valor ( tiempo de actividad )
  • De [PID]/statél utiliza lo siguiente:
 # Nombre Descripción
14 horas de tiempo de CPU en código de usuario, medido en segundos
Tiempo de CPU de 15 tiempos en código kernel, medido en segundos
Tiempo de CPU de 16 cutime dedicado al código de usuario, incluido el tiempo de los niños
17 cstime tiempo de CPU gastado en el código del núcleo, incluido el tiempo de los niños 
22 hora de inicio Hora en que comenzó el proceso, medida en segundos

Un jiffie es la marca del reloj. Por lo tanto, además, utiliza varios métodos, es decir sysconf(_SC_CLK_TCK), para obtener el Hertz del sistema (número de tics por segundo), en última instancia, utiliza 100 como alternativa después de agotar otras opciones.

Entonces, si utimees 1234 y Hertz es 100, entonces:

seconds = utime / Hertz = 1234 / 100 = 12.34

El cálculo real se realiza mediante:

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

Ejemplo (salida de un 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 de la carga "actual" con ps

Este es un esfuerzo sombrío (¿poco?) Pero está bien. Vamos a intentarlo.

Uno podría usar los tiempos provistos por psy calcular el uso de CPU a partir de esto. Al pensar en ello, en realidad podría ser bastante útil, con algunas limitaciones.

Esto podría ser útil para calcular el uso de la CPU durante un período más largo. Es decir, desea monitorear la carga promedio de CPU plugin-containeren Firefox mientras realiza alguna tarea relacionada con Firefox.

Mediante el uso de salida 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.

Yo uso etimemás etimesen esta muestra, en cálculos, sólo para ser un poco más claro. También agrego% cpu para "diversión". Es decir, un script bash que obviamente se usaría etimes, o mejor leer de /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

El proceso estaba usando la CPU el 38% del tiempo durante este período.

Mira el código

Si quieres saber cómo psfunciona, y saber un poco de C, hazlo (parece que ejecutas Gnome Debain deriavnt): buena actitud en el código con respecto a los comentarios, etc.

apt-get source procps
cd procps*/ps
vim HACKING
Runium
fuente
Podría actualizar con más información topy monitoreo continuo, o ajustar por retraso, también conocido como " ps" con la carga actual de la CPU.
Runium
2
Muy buena respuesta!
Theodor
¿Qué pasa cuando se calcula el uso total de la CPU en todo el sistema? ¿Las herramientas intentan obtener el uso de la CPU a través de una instantánea o promediarla con el tiempo?
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
fuente
Hmm, sí, me pregunto cómo obtener eso (el porcentaje de CPU instantánea) deps
Theodor
2
puedes extraer del ejemplo superiortop -p 3343 -n1 | awk '/ R /{print $10}'
Rahul Patil
1
Increíble. Descubrí que awk: para el pidtrabajo funcionó mejor, como entop -p 3343 -n1 | awk '/ 3343 /{print $10}'
Theodor
1
Gracias "top -p" es bueno, ¡nunca me di cuenta de esta opción! Sin embargo, no me gusta buscar el PID, ¿y si por casualidad aparecen los mismos dígitos en la sección de memoria libre o algo así? En mi sistema, la información está en la octava línea y la novena columna, por lo tanto, lo hago:top -p $PID -n1 | awk '{if (NR ==8) print $9 }'
phil_w