[l-linux] Proceso comiendo CPU? Como examino al culpable?

Ernesto Hernandez-Novich emhn at telcel.net.ve
Fri Feb 21 12:09:34 CST 2003


On Tue, 18 Feb 2003, Jean Hendrickx wrote:
> Hola amigos, tengo una aplicación cliente-servido corriendo en un
> Compaq Proliant ML370 con SuSE 8.0 (y el ProvideX server), los clientes
> son máquinas Windows 98SE, ME con el software cliente del lenguaje
> (ProvideX). Estoy usando los puertos 10050 (programas) y 11000 (odbc),
> y todo funciona -aparentemente- bien. El problema es que en la última
> semana el equipo (con solo 3 usuarios) ha disminuido su velocidad hasta
> hacerse casi imposible trabajar con el (un ls tarda hasta 10 segs,
> mostrar el prompt de login [telnet] hasta 15 segs).
>
> Haciendo un top, veo que casi el 100% de actividad del cpu está
> compartido entre el número de usuarios ProvideX (1=(aprox)=99.%,
> 2=(aprox)=50% c/u, 3=(aprox)=32% c/u) ... los valores obtenidos con
> el top son (en una medición de varios minutos durante el proceso de
> "robo de tiempo de procesador"):

El tiempo de CPU tiene tres "calidades":

- Tiempo en espacio usuario. Es el tiempo invertido en operaciones
  "útiles" para la aplicación (aritmética, comparación de cadenas, etc.)
- Tiempo en espacio de sistema. Es el tiempo invertido en operaciones
  necesarias para la aplicación pero que involucran acceso a recursos
  del sistema (reservar memoria, leer/escribir del disco, esperar por
  la red).

Un consumo de CPU de 100% en espacio usuario indica "el proceso es
CPU-bound, si quieres que vaya más rápido, compra un CPU más rápido".
Un consumo de CPU de 100% en espacio sistema indica "el proceso es
I/O-bound, si quieres que vaya más rápido, optimiza el acceso a la
red/disco/memoria o reprograma tu aplicación para que no sea tan
salvaje".

Necesitas saber cual es la distribución user/sys; en aplicaciones
normales escritas por personas que no se secan la baba del mentón, la
proporción habitual es 85/15 como _mucho_.

> %CPU: 	Desde 28% a 99.9%
> SHARE:	348-500
> RSS:		70-170
> SIZE:		310-700M

¿Cuánta memoria RAM tiene la máquina? ¿Cuánta memoria ocupan
_exactamente_ los procesos? El proceso para calcular la cantidad de
memoria exacta consiste en sumar:

a. El producto del tamaño del texto del ejecutable y el número de
   procesos simultáneos. Lo determinas con el comando size.
b. Tamaño compartido entre los procesos una sola vez (es compartido).
   Lo determinas usando ps y convirtiendo de páginas a Kb.
c. Tamaño del espacio privado (stack, DATA + BSS) de cada proceso.
   Lo determinas con ps y convirtiendo de páginas a Kb.
d. Tamaño de los segmentos de memoria compartida entre los procesos
   (si aplica). Lo determinas con ipcs.

Si la sumatoria de éstas medidas [1] cabe en la memoria libre, perfecto,
porque en caso contrario...

> hay otro proceso llamado kswapd que llega a tener hasta 29%, este
> proceso no pertenece al ProvideX, para que se usa este programa?

...vas a estar paginando (y posiblemente swappeando) como un salvaje,
haciendo que el CPU se dedique solamente a intercambiar páginas entre
RAM y swap en lugar de hacer cosas constructivas, llegando al
tristemente conocido síndrome de thrashing.

¿Trataste de escribir free en el apogeo de la crisis?

>Simplemente matando los procesos y re-conectando se resuelve todo,

Porque liberas la memoria.

> Ahora mi pregunta: Adicionalmente al top y ps, existen otros comandos
> (a lá Unix) como sar o cpu_usage que me permitan monitorear más
> cercanamente mi servidor?

ps es suficiente utilizando las opciones adicionales para análisis de
consumo de memoria y CPU.

> Que podría estar disparando estos eventos (uhmm... se que muchos no
> conocen ProvideX, pero podrían tener sugerencias o experiencias con
> problemas parecidos).

Programas/consultas mal escritos que consumen mucha memoria.

[1] Hace años escribí un script que hacía ésto para procesos en
    general, aunque en particular lo hice para la basura que es Oracle.
    Es bastante simple de modificar para cualquier otro servidor.
    No hay ninguna garantía implícita ni explícita, soporte, ni nada
    remotamente relacionado con "necesito algunos cambios".

    Si lo ejecuto como el usuario oracle en mi servidor principal
    tengo algo como

    /opt/oracle> ./mem.pl
    Found shared segment of 927997952 bytes. Correct (y/N) y
    Shared Memory      927997952 bytes
    Binary TEXT         22276376 bytes
    Processes                129 (112 shared servers)
      Total SZ                    123385786368 bytes
      TOTAL RAM         1750672384 bytes   1669.571 Mb
    Tot ziens. Mak ik een bierje?

    Shared Memory y el TEXT son fijos (el primero es un parámetro del
    manejador y el segundo es un tamaño constante). Sin embargo
    Processes varía y definitivamente sus SZ también. En mi caso,
    todos los procesos ocupan 1669.571Mb de RAM que caben
    perfectamente en 2Gb de RAM libres. Y la última línea es un
    chiste privado que quedó en el código.

#!/usr/bin/perl
# Calcula la memoria consumida por Oracle en Linux
# Ernesto Hernández-Novich
#   0.3 - No funcionaba en 2.4. Cambió el formato de ipcs. Enero, 2002
#   0.2 - No funcionaba en 2.2. Cambiaron los flags de ps y no tomaba
#         el comando correcto. Junio 2000
#   0.1 - Version inicial. Junio 1999
# (I hope you dutch bastards stop bothering me for a change,
# start translating van spaans naar neederlander a.u.b :-)
#
# n    = Numero de procesos en la instancia
# SZ   = Paginas de memoria ocupadas por el proceso
# text = Bytes ocupados por el binario Oracle
# shm  = Bytes ocupados en memoria compartida
#
# entonces
#                                   n
# total = (1 - n) * (text + shm) + sum [ SZ(p) en bytes ]
#                                  p=1

my $instance = $ENV{'ORACLE_SID'};
my $oraexec  = $ENV{'ORACLE_HOME'} . "/bin/oracle";

# Usamos ps para determinar cuantos procesos hay en la instancia y
# sumamos sus SZ.

my $ps    = q{/bin/ps -e -o 'pid vsz cmd'};
my $units = 1024;
my $size  = q{/usr/bin/size};
my $ipcs  = q{/usr/bin/ipcs -m};

my $n     = 0;
my $shsrv = 0;
my $sumsz = 0;
my @pids  = ();
open(PS,"$ps |") || die "Can't ps :-P";
while (<PS>) {
  chomp;
  ($pid,$vsz,$command) = split;
  if ($command =~ /$instance$/) {
    $n++;
    $shsrv++ if ($command =~ /_s\d\d\d_/);
    $sumsz += $vsz * $units;
    push(@pids,$pid);
  }
}
close(PS);
@pids = sort { $a <=> $b } @pids;

# Determinamos los bytes ocupados por el texto del binario.

open(SB,"$size $oraexec |") || die "Can't size $oraexec :-b";
while (<SB>) {
  chomp;
  ($text) = split;
  last if $text =~ /^\d+$/;
}
close(SB);

# Determinamos los bytes ocupados por la memoria compartida

my $shm     = 0;
my $correct = "n";
open(IPCS,"$ipcs |") || die "Can't ipcs :-/";
while (<IPCS>) {
  next unless /^0x/;
  chomp;
  (undef,undef,$owner,undef,$size) = split;
  next unless $owner = 'oracle';
  print "Found shared segment of $size bytes. Correct (y/N) ";
  $correct = <>;
  last if ($correct =~ /^y/i);
}
close(IPCS);
$shm = $size if ($correct =~ /^y/i);

$total = ( 1 - $n ) * ( $text + $shm ) + $sumsz;
write;
print "Tot ziens. Mak ik een bierje?\n"

format =
Shared Memory    @########## bytes
$shm
Binary TEXT      @########## bytes
$text
Processes                @## (@## shared servers)
$n,$shsrv
  Total SZ                   @############ bytes
$sumsz
TOTAL RAM        @########## bytes ~ @###.### Mb
$total,($total/1024/1024)
.
-- 
Ernesto Hernández-Novich - Running Linux 2.4.19 i686 - Unix: Live free or die!
Geek by nature, Linux by choice, Debian of course.
If you can't apt-get it, it isn't useful or doesn't exist.
GPG Key Fingerprint = 438C 49A2 A8C7 E7D7 1500 C507 96D6 A3D6 2F4C 85E3

------------------------------------------------------------------------
Enviar e-mail a <majordomo at pm.org> colocando en el cuerpo:
"UNSUBSCRIBE caracas-pm-list" para desuscribirse.
"INFO caracas-pm-list" para conocer las reglas de etiqueta.
------------------------------------------------------------------------



More information about the caracas-pm mailing list