最近开发的一个模块需要根据机房各节点的负载情况(如网卡IO、load average等指标)做任务调度,刚开始对Linux机器load average这项指标不是很清楚,经过调研,终于搞清楚了其计算方法和影响因素,作为笔记,记录于此。
1. load average
        当在shell终端键入top命令时,默认情况下,在输出内容的第一行会有load average这项指标值,如下所示:

top - 19:10:32 up 626 days,  4:58,  1 user,  load average: 7.74, 5.62, 6.51
Tasks: 181 total,   8 running, 173 sleeping,   0 stopped,   0 zombie
Cpu(s):  4.0% us,  0.5% sy,  0.0% ni, 95.4% id,  0.0% wa,  0.0% hi,  0.0% si

同样,输入uptime命令,load average也会被输出:

19:15:10 up 129 days,  5:12, 15 users,  load average: 0.01, 0.09, 0.05    

根据man uptime的说明可知, load average包含的3个值分别表示past 1, 5 and 15 minutes内的系统平均负载。
        那么,这3个值是怎么计算出来的?下面从Linux源码中寻找答案。
2. linux机器load average的计算过程
        wikipedia在对load的解释( 参见这里)中,提到了linux系统对load的计算方法,为亲自验证,我check了linux源码(linux kernel 2.6.9)中的相关代码,自顶向下的验证过程如下。
        在源码树kernel/timer.c文件中,计算系统load的函数代码如下:

// 源码树路径:kernel/timer.c
/** 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.** Requires xtime_lock to access.*/
unsigned long avenrun[3];/** calc_load - given tick count, update the avenrun load estimates.* This is called while holding a write_lock on xtime_lock.*/
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);}
}

从上面的代码可知,定义的数组avenrun[]包含3个元素,分别用于存放past 1, 5 and 15 minutes的load average值。calc_load则是具体的计算函数,其参数ticks表示采样间隔。函数体中,获取当前的活跃进程数(active tasks),然后以其为参数,调用CALC_LOAD分别计算3种load average。
        沿着函数调用链,可以看到count_active_tasks()定义如下(也在kernel/timer.c文件中):

/*  * Nr of active tasks - counted in fixed-point numbers*/
static unsigned long count_active_tasks(void)
{return (nr_running() + nr_uninterruptible()) * FIXED_1;
}

由源码可见,count_active_tasks()返回当前的活跃进程数,其中活跃进程包括:1)当前正在运行的进程(nr_running);2)不可中断的sleeping进程(如正在执行IO操作的被挂起进程)。
        关于nr_running进程和nr_uninterruptible进程的计算方法,可以在源码树kernel/schde.c中看到相关代码:

// 源码树路径:kernel/sched.c
/** nr_running, nr_uninterruptible and nr_context_switches:** externally visible scheduler statistics: current number of runnable* threads, current number of uninterruptible-sleeping threads, total* number of context switches performed since bootup.*/
unsigned long nr_running(void)
{unsigned long i, sum = 0;for (i = 0; i < NR_CPUS; i++)sum += cpu_rq(i)->nr_running;return sum;
}unsigned long nr_uninterruptible(void)
{unsigned long i, sum = 0;for_each_cpu(i)sum += cpu_rq(i)->nr_uninterruptible;return sum;
}

继续沿着函数调用链查看,可在include/linux/sched.h中看到CALC_LOAD的定义:

// 源码树路径: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;

可以看到,CALC_LOAD是一个宏定义,load average的值与3个参数相关,但若只考虑某1项指标值(如past 5 minutes的load average),则该值只受当前活跃进程数(active tasks)的影响,而活跃进程数包括两种:当前正在运行的进程和不可中断的挂起进程。
        这符合我的观察结果:三台硬件配置相同的linux机器(8 cup, 16GB memory, 1.8T disk),在当前总进程数相差不多(均为170+)的情况下,其中1台机器有1个普通进程(这里的"普通"是指既非CPU型又非IO型)在运行,其余均sleeping;第2台机器有5个cpu型进程,cpu占用率均达到99%,其余进程sleeping;第3台机器2个进程读写硬盘,其余sleeping。很明显地可以看到:第3台机器的load average指标的3个值均为最大,第2台机器次之,第1台机器的3个值均接近0。
        由此,还可以推断出:与running类型的进程相比,uninterruptible类型的进程(如正在进行IO操作)对系统load的影响较大。( 注:该推断暂无数据或代码支撑,若有误,欢迎指正)

3. 理解load average背后的含义
        上面介绍了load average的概念及linux系统对该指标的计算过程,那么,这个指标值到底怎么解读呢?这篇文章给出了详细且形象的说明,此处不再赘述。

【参考资料】
1. wikipedia: Load (computing) 
2. linux源码(内核版本2.6.9)
3. Understanding Linux CPU Load - when should you be worried?

================== EOF ===================

linux主机load average的概念计算过程注意事项相关推荐

  1. Linux系统load average异常值处理的trick

    周末再分享一个内核bug紧急热处理case. 假如你发现某个Linux系统的load输出如下: #uptime ... 0 users, load average: 32534565100.09, 3 ...

  2. 容器CPU使用率过高,导致宿主机load average飙升

    早上醒来已经收到多条服务器告警信息,具体是这样的,如下图:Processor load (15 min average per core) ;服务器CPU load 过高,接下来是处理过程,记录一下. ...

  3. Linux操作系统load average过高,kworker占用较多cpu

    Linux操作系统load average过高,kworker占用较多cpu 今天巡检发现,mc1的K8S服务器集群有些异常,负载不太均衡.其中10.2.75.32-34,49的load averag ...

  4. linux系统oracle启动过程,Linux主机下配置Oracle 10G自动启动过程记

    四:创建服务 $su - root # cd /etc/rc.d/init.d/ # gedit oradbstart 复制如下脚本1或者脚本2内容到oradbstart文件: 注意点 (1).#开始 ...

  5. 深入理解 Linux Load Average

    一直不解,为什么io占用较高时,系统负载也会变高,偶遇此文,终解吾惑. #1 load average介绍 ##1.1 load average 指标介绍 uptime和top等命令都可以看到load ...

  6. 详解多分类模型的Macro-F1/Precision/Recall计算过程

    引入 关于准确率(accuracy).精度(precision).查全率(recall).F1的计算过程,之前写过一篇文章[1]. 根据文章[1]中的公式,我们可以知道,精度(precision).查 ...

  7. LINUX下CPU Load Average的一点研究

    背景: 公司的某个系统工作在基于Linux的Cent OS下,一个host下同时连接了许多client, 最近某台Host总是显示CPU Load Average过高,我们单纯的以为是CPU的占用过高 ...

  8. php 系统平均负载,Linux_解析Linux系统的平均负载概念,一、什么是系统平均负载(Load a - phpStudy...

    解析Linux系统的平均负载概念 一.什么是系统平均负载(Load average)?在Linux系统中,uptime.w.top等命令都会有系统平均负载load average的输出,那么什么是系统 ...

  9. linux中负载值为多少正常_Linux load average负载量分析与解决思路

    一.load average top命令中load average显示的是最近1分钟.5分钟和15分钟的系统平均负载.系统平均负载表示 系统平均负载被定义为在特定时间间隔内运行队列中(在CPU上运行或 ...

最新文章

  1. 多线程-Thread、Runnable、Callbale、Future
  2. 巨坑!同事离职前一天,偷偷将一个470欧的色环电阻串进我的电源线中......
  3. 关于Java里如何跳出一个多重循环
  4. typecho怎么用html编写文章,为Typecho文章增加HTML标签支持
  5. 从零开始学习MXnet(四)计算图和粗细粒度以及自动求导
  6. JAVA压缩、解压,使用Apache Common Compress包下载链接
  7. matlab 梁代码,方舟生存进化梁龙鞍怎么做 梁龙鞍代码材料一览
  8. 国产6678开发记录
  9. 微信小程序开发常用方法
  10. html中左三角怎么写,css3三角形怎么写?
  11. 创业公司一年工作总结(转)(公司失败原因)
  12. 电脑笑脸蓝屏问题 也许你可以尝试一下这个
  13. 深大uooc学术道德与学术规范教育第七章
  14. Android源码中的目录结构详解
  15. 1081:分苹果(C C++)
  16. 在matlab中理解采样定理
  17. 武大计算机科学与技术弘毅学堂,武汉大学研究生精品课-百余新学子体验“弘毅学堂”...
  18. 架构设计文档提纲简描
  19. 轻松上手UAI-Train,拍拍贷人脸识别算法优化效率提升85.7%
  20. 6-Python数字和列表

热门文章

  1. token和session的区别
  2. mongodb如何快速进行版本升级
  3. 卷积输出的记录,为什么是([3, 0, 1, 2])
  4. linux下mysql开启远程访问权限及防火墙开放3306端口(mysql开放host访问权限)
  5. 每一个程序员都应该知道的高并发处理技巧、创业公司如何解决高并发问题、互联网高并发问题解决思路、caoz大神多年经验总结分享...
  6. Spring的IOC原理
  7. 29. Divide Two Integers
  8. Delphi RTC
  9. nullnullanimate用法
  10. BZOJ 1562 变换序列