Load Average含义
top命令中的Load Average显示的三个值表示在过去1分钟、5分钟、15分钟的系统负载。
top命令中load average由来
top命令直接从/proc/loadavg文件中读取值,没有做转换工作,该文件记录了系统在前1分钟、前5分钟和前15分钟的平均负载。
[root@linux_driver programming]# cat /proc/loadavg
0.06 0.03 0.00 2/309 28525
[root@linux_driver programming]#
负载的含义
影响load average值大小的直接因素是系统中活动的进程数。Linux的系统负载指运行队列的平均长度,也就是等待CPU的平均进程数。活动的进程数可以很直观表明系统负载情况。值越大,表明CPU上正在运行和待运行的进程数越多,也就是负载越大。
系统中正在运行的进程越多,load average的值越大(等待CPU运行的进程队列越长)。
Load Average越大,表明需要CPU干的活越多。
活动进程含义
活动进程:处于TASK_RUNNING和TASK_UNINTERRUPTIBLE状态的进程。
进程的状态有以下7种。
TASK_RUNNING
进程处于运行(它是系统的当前进程)或者准备运行状态(它在等待系统将CPU分配给它)
TASK_INTERRUPTIBLE
等待某个条件:中断、信号或能唤醒进程的资源
TASK_UNINTERRUPTIBLE
处于睡眠状态,信号无法唤醒它。
TASK_STOPPED
进程停止,当进程收到SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU信号时就会进入次状态
TASK_TRACED
进程执行被调试器停止(调试程序使用ptrace()系统调用来监控程序)
EXIT_ZOMBIE
进程执行停止,但父进程还没调用wait4()或waitpid()来获取该进程返回信息。
EXIT_DEAD
进程的最终状态,父进程调用wait4()或waitpid()来获取该进程返回信息,内核即将移除该进程。
Linux内核对load average的计算
内核通过下面的算式计算负载:
load(t) = load(t-1) e-5/60R + n(t) (1 – e-5/60R)
n(t)是系统活动的进程数, R对应1、5、15分钟(如当计算15分钟的平均负载时,R的值就为15)。
Linux内核认为进程的生存时间服从参数为1的指数分布,指数分布的概率密度为:以内核计算负载load1为例,设相邻两个计算时刻之间系统活动的进程集合为S0。从1分钟前到当前计算时刻这段时间里面活动的load1个进程,设他们的集合是S1,内核认为的概率密度是:λe-λx,而在当前时刻活动的n个进程,设他们的集合是Sn内核认为的概率密度是1-λe-λx。其中 x = 5 / 60,因为相邻两个计算时刻之间进程所耗的CPU时间为5秒,而考虑的时间段是1分钟(60秒)。那么可以求出最近1分钟系统运行队列的长度:
load1
– –= |S1| –* λe-λx + |Sn| * (1-λe-λx)
– –= load1 * λe-λx + n * (1-λe-λx)
其中λ = 1, x = 5 / 60, |S1|和|Sn|是集合元素的个数。
Linux内核定义一个unsigned long类型数组avenrun[3],因为内核不能使用浮点数,就将低11位用于存放负载的小数部分,高21位用于存放整数部分。
avenrun[0]对应前1分钟系统负载;
avenrun[1]对应前5分钟系统负载;
avenrun[2]对应前15分钟系统负载;
内核每隔5秒钟更新一次load average的值。
01345:/*
01346:*calc_load-giventick count,updatetheavenrunloadestimates.
01347:*Thisiscalledwhile holdingawrite_lockonxtime_lock.
01348:*/
01349:staticinlinevoid calc_load(unsignedlong ticks)
01350:{
01351: unsignedlongactive_tasks;/*fixed-point*/
01352: staticint count=LOAD_FREQ;
01353:
01354: count–=ticks;
01355: if(count<0){
01356: count+=LOAD_FREQ;
01357: active_tasks=count_active_tasks();
01358: CALC_LOAD(avenrun[0],EXP_1,active_tasks);
01359: CALC_LOAD(avenrun[1],EXP_5,active_tasks);
01360: CALC_LOAD(avenrun[2],EXP_15,active_tasks);
01361: }
01362:}
01325:/*
01326:*Nrofactive tasks-countedinfixed-pointnumbers
01327:*/
01328:staticunsignedlong count_active_tasks(void)
01329:{
01330: returnnr_active()* FIXED_1;
01331:}
02116:unsignedlong nr_active(void)
02117:{
02118: unsignedlong i,running=0,uninterruptible=0;
02119:
02120: for_each_online_cpu(i){
02121: running+=cpu_rq(i)–>nr_running;
02122: uninterruptible +=cpu_rq(i)–>nr_uninterruptible;
02123: }
02124:
02125: if(unlikely((long)uninterruptible<0))
02126: uninterruptible =0;
02127:
02128: returnrunning+uninterruptible;
02129:}
00107:externunsignedlongavenrun[]; /*Loadaverages*/
00108:
00109:#defineFSHIFT 11 /*nrofbitsofprecision*/
00110:#defineFIXED_1 (1<<FSHIFT)/* 1.0asfixed-point*/
00111:#defineLOAD_FREQ (5*HZ) /*5secintervals*/
00112:#defineEXP_1 1884 /*1/exp(5sec/1min)asfixed-point*/
00113:#defineEXP_5 2014 /*1/exp(5sec/5min)*/
00114:#defineEXP_15 2037 /*1/exp(5sec/15min)*/
00115:
00116:#defineCALC_LOAD(load,exp,n)\
00117: load*=exp;\
00118: load+=n*(FIXED_1–exp);\
00119: load>>=FSHIFT;
系统负载值的计算代码非常简单,但比较难以理解。主要是EXP_1, EXP_5, EXP_15几个值,为什么是1884、2014和2037。
EXP_R = 211/2 [(5 log2(e))/ 60R]
R对应1、5、15分钟(如当计算15分钟的平均负载时,R的值就为15)。
R |
EXP_R |
Rnd |
1 |
1884.25 |
1884 |
5 |
2014.15 |
2014 |
15 |
2036.65 |
203 |
Leave a Reply