BULMA Bulma amb el projecta Defective by Desing
Bergantells Usuaris de GNU/Linux de Mallorca i Afegitons   |   Bisoños Usuarios de GNU/Linux de Mallorca y Alrededores
CONTENIDOS
. Jornadas de software libre
. Version para PDA
. Enlaces breves
. La asociacion
. Los mas leidos
. Autores [Actividad]
. Ultimos Comentarios
. Todos los titulares!
. Estadisticas
. Guia de estilo
. ¿Sugerencias?
. Wiki
. XML [Ayuda]
Listas de correo
. Archivos bulmailing
. Archivos BulmaGes
Radio libre :-)
. Des de la Xarxa (Archivos)
. Mallorca en Xarxa
Busquedas

+ Enlaces Linux
Ultimos kernels
(09/02/2010 14:25:46)
    
Google


En bulma.net
En internet
¿Cómo se calculan los promedios del loadavg en el Linux? (8939 lectures)
Por Ricardo Galli Granada
gallir (http://mnm.uib.es/gallir/)
Creado el 09/03/2001 00:00 modificado el 09/03/2001 00:00

Pregunta: En diversas ocasiones he oido hablar del comando w, y de que es utilizado para mirar la carga de un ordenador. Me gustaría saber que significan los tres números esos del final de la primera linea. He leido que son la carga media durante los últimos 1, 5 y 15 minutos, pero querría saber en que escala está. Supongo que como más grandes sean los números, más carga tendrás.

Pagina1/1

Los números que muestra el w o el uptime, como bien dices, son los promedios (aproximados) exponenciales de la "carga". La carga es sencillamente el número de procesos en la cola de listos para ejecutar del kernel (active_tasks).

Si tienes un solo proceso haciendo sólo cálculo, el valor de la carga será uno. Básicamente te dá una idea del promedio de procesos compitiendo por CPU. En la mayoría de los casos, prácticamente todos los procesos están bloqueados por entrada/salida, por lo que las cargas serán muy bajas (ver también respuesta de Guillem Cantallops).

Forma de cálculo

La formula para calcular el valor actual de la carga es:

h = Historia (y promedio)
x = Último valor

h = h * EXP + (1 - EXP) * x

Para calcular el EXP a usar para 1, 5 y 15 minutos se hace:

1 minuto

EXP_1 = 1 / exp(5 seg/1 min) = 1/exp(1/12) =~ 0.91

5 minutos

EXP_5 = 1 / exp(5 seg/5 min) = 1/exp(1/60) =~ 0.98

15 minutos

EXP_15 = 1 / exp(5 seg/15 min) = 1/exp(1/180) =~ 0.99

Se observa que cuanto más grande es EXP, la historia "permanece" por mas tiempo. Se puede decir que la historia tiene un "valor de decaimiento" (decay) de 0.91 para el primer caso, 0.98 para el segundo y 0.99 para el tercero.

Evolución de los promedios

Supongamos que en h(0) el valor de la carga fue 1, y que luego todos los valores instantáneos medidos cada 5 segundos fueron 0. Con la evolución del tiempo veremos que pasa para algunos h(t). Recordar que en Linux, cada t son 5 segundos.

Tiempo t 1 min 5 min 15 min
0 seg 0 1.00 1.00 1.00
5 seg 1 0.92 0.98 0.98
15 seg 3 0.72 0.95 0.98
1 min 12 0.37 0.82 0.94
3 min 36 0.05 0.54 0.82
5 min 60 0.00 0.36 0.71
15 min 180 0.00 0.04 0.35

Implementación en el Kernel

Estas operaciones en el kernel se hacen con aritmética entera, por lo que el código es un poco más complejo.

La función que calcula en el kernel está en linux/kernel/timer.c.

linux/kernel/timer.c
 
// Se llama desde update_times(void) 
static inline void calc_load(unsigned long ticks) 
{ 
    ... 
    // Se ejecuta cada 5 segundos 
        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); 
    } 
} 

pero necesita de las definiciones en linux/include/linux/sched.h.

linux/include/linux/sched.h
 
#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; 
 
// Desplaza el valor anterior en 11 bits a la izquierda 

La función que imprime los valores de carga en /proc/loadavg está en linux/fs/proc/proc_misc.c

 
static int loadavg_read_proc(char *page, char **start, off_t off, 
                 int count, int *eof, void *data) 

A continuación hay un pequeño programa en C que simula los resultados del loadavg para unos pocos intervalos de tiempo

Ejemplo: simloadavg.c

 
// gallir@uib.es, 2001 
#include  
#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 */ 
                     // Esto es igual a 1884/2048 = 0.919921... 
#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; 
 
#define LOAD_INT(x) ((x) >> FSHIFT) 
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) 
 
 
void imprimir_linea_pf(unsigned long *); 
 
main() 
{ 
        unsigned long a[] = { FIXED_1, FIXED_1, FIXED_1};  
		// La carga anterior, 1 en punto fijo 
        unsigned long active_tasks = 0;  
		// Simulamos que no hay mas carga 
        int i, step; 
 
        printf("Exponenciales: %d.%02d %d.%02d %d.%02d\n", 
                LOAD_INT(EXP_1), LOAD_FRAC(EXP_1), 
        LOAD_INT(EXP_5), LOAD_FRAC(EXP_5), 
        LOAD_INT(EXP_15), LOAD_FRAC(EXP_15)); 
 
        for(step=1; step<24; step++) {  
              // Cada step son 5 segundos... 
              // simulamos 2 minutos 
                CALC_LOAD(a[0], EXP_1, active_tasks); 
                CALC_LOAD(a[1], EXP_5, active_tasks); 
                CALC_LOAD(a[2], EXP_15, active_tasks); 
                printf("Step (5 seg) = %d ", step); 
                imprimir_linea_pf(a); 
        } 
} 
 
/****** Está en linux/fs/proc/proc_misc.c 
static int loadavg_read_proc(char *page, char **start, off_t off, 
                 int count, int *eof, void *data) 
****/ 
 
 
void imprimir_linea_pf(unsigned long avenrun[]) 
{ 
    int a, b, c; 
    int len; 
        char line[256]; 
 
    a = avenrun[0] + (FIXED_1/200); // Redondeo 
    b = avenrun[1] + (FIXED_1/200); // Redondeo 
    c = avenrun[2] + (FIXED_1/200); // Redondeo 
    len = sprintf(line,"%d.%02d %d.%02d %d.%02d \n", 
        LOAD_INT(a), LOAD_FRAC(a), 
        LOAD_INT(b), LOAD_FRAC(b), 
        LOAD_INT(c), LOAD_FRAC(c)); 
        printf(line); 
} 

Imprimir
Version para
imprimir

Imprimir
Version
PDF
Comentarios
Es posible que se hayan omitido algunos comentarios considerados poco constructivos
GRACIAS
Distribuciones Universal
Por el servidor
Dpto. de Matematicas e Informatica
Calificacion
***0
Vots: 9
Danos tu opinion:
**** Excelente
***0 Muy Bueno
**00 Bueno
*000 Regular
0000 Malo
SECCIONES
Noticia
Breve
Truco
Enlace
Participa
Proyecto
Articulo
Webbulma
Manoletada :-)
Seguridad
Modificado: 12/1/2010 15:49:10 | Tiempo Total: 0.065 segs | Kernel: Linux - i686 - 2.6.26-1-686 | Last boot: 09/02/2010 15:46 CET
Powered by Apache    MySQL    PHP    Gimp