Load
Let's dive into load average.
Sample output of `uptime':
18:38:47 up 28 days, 9:15, 9 users, load average: 2.63, 2.67, 2.50
当前时间, 系统运行时间, 目前登录用户数, 过去1/5/15 min的平均负载
什么是load average?
来自于uptime(1)
System load averages is the average number of processes that are either
in a runnable or uninterruptable state. A process in a runnable state
is either using the CPU or waiting to use the CPU. A process in unin‐
terruptable state is waiting for some I/O access, eg waiting for disk.
The averages are taken over the three time intervals. Load averages
are not normalized for the number of CPUs in a system, so a load aver‐
age of 1 means a single CPU system is loaded all the time while on a 4
CPU system it means it was idle 75% of the time.
Kernel magic:
source code in kernel/sched.c, include/linux/sched.h
/* calc_global_load function */ 3252 avenrun[0] = calc_load(avenrun[0], EXP_1, active); /* 1min */ 3253 avenrun[1] = calc_load(avenrun[1], EXP_5, active); /* 5min */ 3254 avenrun[2] = calc_load(avenrun[2], EXP_15, active);/* 15min */ 3256 calc_load_update += LOAD_FREQ;
而calc_load 的定义:
3046 static unsigned long 3047 calc_load(unsigned long load, unsigned long exp, unsigned long active) 3048 { 3049 load *= exp;; 3050 load += active * (FIXED_1 - exp); 3051 load += 1UL << (FSHIFT - 1); 3052 return load >> FSHIFT; 3053 }
故计算公式:
load(t1) = (load(t0)*exp + active*(FIXED_1-exp)) >> FSHIFT
exp 有EXP_1, EXP_5, EXP_15, 对应1min, 5min, 15min.
但EXP_*, FSHIFT, FIXED_1 又是什么?
/* * 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. */ 125 #define FSHIFT 11 /* nr of bits of precision */ 126 #define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */ 127 #define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */ 128 #define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */ 129 #define EXP_5 2014 /* 1/exp(5sec/5min) */ 130 #define EXP_15 2037 /* 1/exp(5sec/15min) */
由此可知真正的计算公式:
load(t1) = load(t0) * exp_m + active * (1 - exp_m)
其中exp_m 对应于EXP_M, 是小于1的常量, 称之为负载因子, 作为前次负载的比重。
EPX_* 是如何计算的?
代码实现的exp_m = exp(-load_freq/m), load_freq 为更新频率
由于每隔5s进行负载计算的更新, 过去 m min的负载因子
exp_m = exp(-5s/60ms), 所以
EXP_M = exp_m << FSHIFT
= 2**11 * exp(-5/60m)
= 2**(11 - 5*log2(e)/60m)
EXP_1 = 2**(11 - 5*log2(e)/60) = 1884
同理EXP_5 = 2014, EXP_15 = 2037
reference:
http://en.wikipedia.org/wiki/Load_(computing)
http://www.teamquest.com/pdfs/whitepaper/ldavg1.pdf