What is the Linux CPU Load
The load average represents the average system load over a period of time. It conventionally appears in the form of three numbers which represent the system load during the last one-, five-, and fifteen-minute periods. https://en.wikipedia.org/wiki/Load_(computing)
按照网上看到的一种很形象的说法,假设我们的系统是单 CPU 单内核的,把它比喻成是一条单向马路,把任务比作汽车。
- 当车不多的时候,load <1;
- 当车占满整个马路的时候, load=1;
- 当马路都站满了,而且马路外还堆满了汽车的时候,load>1
Linux 机器上,有很多工具可以查看过去一段时间的平均负载,比如:htop
,top
,w
,uptime
等等。至于它们的数据来源,都是从 /proc/loadavg
读取到的,比如:
$ cat /proc/loadavg
1.07 1.27 0.94 1/3934 1168925
loadavg 的算法及实现
loadavg 的实现在 kernel/sched/loadavg.c
文件里,文件开头写了一段算法说明,摘录如下:
The global load average is an exponentially decaying average of nr_running + nr_uninterruptible.
Once every LOAD_FREQ:
nr_active = 0;
for_each_possible_cpu(cpu)
nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible;
avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)
所以 loadavg 是 nr_running + nr_uninterruptible
状态线程数量的一个指数衰减平均,每隔 LOAD_FREQ(5 秒)把过去 n(取 1、5、15) 分钟里的 loadavg 计算一次。
其中的 exp_n = e^(-LOAD_FREQ/(60*n))
,比如 exp_1 = 0.92004
,exp_5 = 0.98347
,exp_15 = 0.99446
。
在 include/linux/sched/loadavg.h
里,定义了几个常数,其目的是使用整数的乘法和移位操作,来避免复杂的浮点和指数运算:
#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_FREQ (5*HZ+1) /* 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) */
/*
* a1 = a0 * e + a * (1 - e)
*/
static inline unsigned long
calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
unsigned long newload;
newload = load * exp + active * (FIXED_1 - exp);
if (active >= load)
newload += FIXED_1-1;
return newload / FIXED_1;
}
比如,当 n = 1 分钟时,这时的 #define EXP_1 1884
,所以 load * exp_1 = load * 0.9200 = load * 1884 / 2048,这样就简化为先计算 load * EXP_1,再右移 11 位可以得到结果。
参考资料:
- Understanding Linux CPU Load - when should you be worried? http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages
- 理解 Linux 的处理器负载均值(翻译) http://www.gracecode.com/posts/2973.html
- 理解 Linux 系统中的 load average(图文版)http://heipark.iteye.com/blog/1340384
- https://arthurchiao.art/blog/linux-loadavg-zh/