linux主机load average的概念&&计算过程&&注意事项
最近开发的一个模块需要根据机房各节点的负载情况(如网卡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的概念&&计算过程&&注意事项的更多相关文章
- Linux 通过 load average 判断服务器负载情况
Linux中load average判断服务器负载情况 转载文章 http://www.111cn.net/sys/linux/56003.htm 写的比较详细,推荐看看.
- Linux操作系统load average过高,kworker占用较多cpu
Linux操作系统load average过高,kworker占用较多cpu 今天巡检发现,mc1的K8S服务器集群有些异常,负载不太均衡.其中10.2.75.32-34,49的load averag ...
- Linux系统Load average负载详细解释
我们知道判断一个系统的负载可以使用top,uptime等命令去查看,它分别记录了一分钟.五分钟.以及十五分钟的系统平均负载 例如我的某台服务器: $ uptime 09:50:21 up 200 da ...
- [进程管理] Linux中Load average的理解
Load average的定义 系统平均负载被定义为在特定时间间隔内运行队列中的平均进程树.如果一个进程满足以下条件则其就会位于运行队列中: - 它没有在等待I/O操作的结果 - 它没有主动进入等待状 ...
- 理解Linux系统负荷load average
理解Linux系统负荷 一.查看系统负荷 如果你的电脑很慢,你或许想查看一下,它的工作量是否太大了. 在Linux系统中,我们一般使用uptime命令查看(w命令和top命令也行).(另外,它们在 ...
- Linux CPU Load Average
理解Linux系统负荷 LINUX下CPU Load Average的一点研究 Linux load average负载量分析与解决思路 Understanding Linux CPU Load - ...
- 理解LINUX LOAD AVERAGE的误区
一直不解,为什么io占用较高时,系统负载也会变高,偶遇此文,终解吾惑. uptime和top等命令都可以看到load average指标,从左至右三个数字分别表示1分钟.5分钟.15分钟的load a ...
- top命令的Load average 含义及性能参考基值
$ uptime11:12:26 up 3:44, 4 users, load average: 0.38, 0.31, 0.19 系统平均负载被定义为在特定时间间隔内运行队列中的平均进程树.如果一个 ...
- LINUX下CPU Load Average的一点研究
背景: 公司的某个系统工作在基于Linux的Cent OS下,一个host下同时连接了许多client, 最近某台Host总是显示CPU Load Average过高,我们单纯的以为是CPU的占用过高 ...
随机推荐
- EasyMonkeyDevice vs MonkeyDevice&HierarchyViewer API Mapping Matrix
1. 前言 本来这次文章的title是写成和前几篇类似的<EasyMonkeyDevice API实践全记录>,内容也打算把每个API的实践和建议给记录下来,但后来想了下觉得这样子并不是最 ...
- OpenSUSE 13.2使用VPN(PPTP)
新年开始,有时查询个资料或是下个软件包并不是那么愉快,决定使用付费VPN,他们使用的是用户名及密码的验证方式 在网上找到了一个教程,挺详尽的,如果想按照步骤能使用即可的原则,跟着我一起设置,想了解更多 ...
- UC编程:字符读取与行读取
字符读取函数的应用 下面的演示程序实现从/etc/passwd文件中提取用户名,打印到屏幕上并保存在copyname.txt文件中 使用的函数是getc().putc().putchar() [c] ...
- vim的复制粘贴小结
vim帮助文档里与粘贴板有关的内容如下: vim有12个粘贴板,分别是0.1.2.….9.a.“.+:用:reg命令可以查看各个粘贴板里的内容.在vim中简单用y只是复制到“(双引号)粘贴板里,同样用 ...
- Java中间Map List Set和其他收藏品
Map List Set和其他收藏品: 一.概述 在JAVA的util包中有两个全部集合的父接口Collection和Map,它们的父子关系: +Collection 这个接口extends自 --j ...
- JS判断鼠标向上滚动还是向下滚动
js如何判断滚轮的上下滚动,我们应该都见到过这种效果,用鼠标滚轮实现某个表单内的数字向上滚动就增加,向下滚动就减少的操作,这种效果是通过js对鼠标滚轮的事件监听来实现的.今天简单的研究了一下如何使用j ...
- 用mysql dump 导入与导出的方法
用mysql dump 导入与导出的方法 分类: 数据库2009-12-08 00:04 6825人阅读 评论(0) 收藏 举报 mysql数据库deleteinsertinternetdatabas ...
- 【转】视差滚动(Parallax Scrolling)效果的原理和实现
原文:http://www.cnblogs.com/JoannaQ/archive/2013/02/08/2909111.html 视差滚动(Parallax Scrolling)是指让多层背景以不同 ...
- QTP脚本不能录制怎么办?
QTP是基于VBS脚本语言的,大部分VBS脚本都能在QTP上运行,只是在一些细节上略有不同,比如说VBS上停止用sleep,QTP上用wait.QTP的强大之处在于对程序窗口的操作,有很多针对窗体的属 ...
- .net图片压缩
1.png很难进行压缩,一般压缩时间较长. 2.jpg图片压缩方法: #region 图片压缩[之压缩jpg] public static void JpgImgZip(Image img,strin ...