Re: [maillist] Genaue Definition von der load

Klaus Muth (monty@unitopia.de)
Sun, 24 Oct 1999 13:52:42 +0200

Heiko Romahn wrote:
>
> Hi,
>
> hat hier jemand die genaue Definition der Load?
Use the source, Luke. Ich hab mir mal die Muehe gemacht, im Source
zu suchen, da in den Manpages nur drin steht, dass xload, tload,
w und uoptime eben den "durchschnittlichen Load der letzten 1, 5 und
15 Minuten" anzeigen. Das haben die, laut man aus /proc/loadavg.
Also mal in den Kernelsourcen nach "loadavg" suchen:
find /usr/src/linux -type f | xargs grep "loadavg"
foerdert /usr/src/linux/fs/proc/root.c zutage mit dem Codebröckel
-------------
static struct proc_dir_entry proc_root_loadavg = {
PROC_LOADAVG, 7, "loadavg",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
-------------
Hilft nicht arg. Was ist PROC_LOADAVG?
find /usr/src/linux -type f | xargs grep "PROC_LOADAVG"
liefert /usr/src/linux/fs/proc/array.c, da findet man:

-------------
case PROC_LOADAVG:
return get_loadavg(page);

.....
static int get_loadavg(char * buffer)
{
int a, b, c;

a = avenrun[0] + (FIXED_1/200);
b = avenrun[1] + (FIXED_1/200);
c = avenrun[2] + (FIXED_1/200);
return sprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
LOAD_INT(a), LOAD_FRAC(a),
LOAD_INT(b), LOAD_FRAC(b),
LOAD_INT(c), LOAD_FRAC(c),
nr_running, nr_tasks, last_pid);
}
-------------
Ok, das Format aus dem sprintf entspricht genaud dem von /proc/loadavg und
avenrun findet man (den find schreib ich nimmer hin) im Schduler
/usr/src/linux/kernel/sched.c (naja, haette man sich auch denken können)
-------------
/*
* Hmm.. Changed this, as the GNU make sources (load.c) seems to
* imply that avenrun[] is the standard name for this kind of thing.
* Nothing else seems to be standardized: the fractional size etc
* all seem to differ on different machines.
*/
unsigned long avenrun[3] = { 0,0,0 };

/*
* Nr of active tasks - counted in fixed-point numbers
*/
static unsigned long count_active_tasks(void)
{
struct task_struct *p;
unsigned long nr = 0;

read_lock(&tasklist_lock);
for_each_task(p) {
if ((p->state == TASK_RUNNING ||
p->state == TASK_UNINTERRUPTIBLE ||
p->state == TASK_SWAPPING))
nr += FIXED_1;
}
read_unlock(&tasklist_lock);
return nr;
}

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);
}
}

-------------
und endlich in /usr/src/linux/include/linux/sched.h:
-------------
/*
* These are the constant used to fake the fixed-point load-average
* counting. Some notes:
* - 11 bit fractions expand to 22 bits by the multiplies: this gives
* a load-average precision of 10 bits integer + 11 bits fractional
* - if you want to count load-averages more often, you need more
* precision, or rounding will get you. With 2-second counting freq,
* the EXP_n values would be 1981, 2034 and 2043 if still using only
* 11 bit fractions.
*/
extern unsigned long avenrun[]; /* Load averages */

#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;
-------------
Hmmm. Sieht so aus, als sei der Load die Anzahl der Prozesse, die
durchschnittlich in den letzten N Minuten auf dem Prozessor gleichzeitig
aktiv waren.

klaus

-- 
Klaus Muth                             privat        monty@unitopia.de
                                       geschaeftlich     muth@hagos.de
----------------------------------------------------------------------
telnet:unitopia.de                           http://unitopia.de/~monty