深入理解load averages

本文翻译自 linux-load-averages,按照译者理解有删减

前言

经常和Linux打交道的童鞋都知道,load averages是衡量机器负载的关键指标,但是这个指标是怎样定义出来的呢?

和其他系统不同,Linux上的load averages不仅追踪可运行的任务,还追踪处于不可中断睡眠状态的任务,为什么是这样呢?这篇文章就来聊聊这方面的知识。

Linux的load averages是系统负载平均值,这个值将正在运行线程(任务)对于系统的需求,作为处于运行和等待状态的线程的平均数量。大多数工具会显示1分钟,5分钟和15分钟的平均值:

$ uptime
 17:30:01 up 13 days, 20:30,  3 users,  load average: 1.66, 2.03, 2.08
 
$ cat /proc/loadavg
1.48 1.98 2.06 4/3587 117385

对上面的输出信息稍稍做些解释

  • 如果平均值是0.0,说明系统处于空闲状态
  • 如果1分钟的平均值大于5分钟或者15分钟,说明系统负载正在增加
  • 如果1分钟的平均值小于5分钟或者15分钟,说明系统负载正在减小
  • 如果这些值大于CPU的核数,说明可能遇到了性能问题

利用这三个值,我们可以判断系统的负载是在增加还是在减小,这在实践中很有用。这三个中的任意一个拿出来也很有用,比如为云服务的自动伸缩设置阈值。不过,在缺少其他信息的情况下,单看这些值是没有意义的。比如1分钟的load averages值在23到25之间,就没有任何意义;但如果知道CPU核数并且知道运行的任务是计算密集型,那这个值就很有意义。

历史

最开始的时候,load averages只显示对系统CPU相关的需求:运行的进程数加上等待的进程数。如RFC 546描述的

TENEX load averages是衡量CPU需求的指标。这个值是给定时间内可运行进程数量的平均值。例如,对于单核CPU系统,每小时平均10次意思是在该小时内可以期望看到一个进程正在运行和另外九个等待CPU(即没有被I/O阻塞)处于ready状态的进程。

下图是1973年绘制的监控图
image

以前操作系统的代码还可以找到,下面是TENEX定义的一些宏

NRJAVS==3               ;NUMBER OF LOAD AVERAGES WE MAINTAIN
GS RJAV,NRJAVS          ;EXPONENTIAL AVERAGES OF NUMBER OF ACTIVE PROCESSES
[...]
;UPDATE RUNNABLE JOB AVERAGES

DORJAV: MOVEI 2,^D5000
        MOVEM 2,RJATIM          ;SET TIME OF NEXT UPDATE
        MOVE 4,RJTSUM           ;CURRENT INTEGRAL OF NBPROC+NGPROC
        SUBM 4,RJAVS1           ;DIFFERENCE FROM LAST UPDATE
        EXCH 4,RJAVS1
        FSC 4,233               ;FLOAT IT
        FDVR 4,[5000.0]         ;AVERAGE OVER LAST 5000 MS
[...]
;TABLE OF EXP(-T/C) FOR T = 5 SEC.

EXPFF:  EXP 0.920043902 ;C = 1 MIN
        EXP 0.983471344 ;C = 5 MIN
        EXP 0.994459811 ;C = 15 MIN

Linux中定义的宏长下面这样(代码出处include/linux/sched/loadavg.h):

#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) */

指标的三个粒度

load averages有1分钟,5分钟,15分钟三个粒度的结果。不过事实上,他们并不是真正的平均值,统计的粒度也不是1,5,15分钟。从上面的代码中可以看出,1,5和15都是常量,用于计算指数衰减的5秒平均移动和。由此算出的1分钟,5分钟和15分钟的load averages所反应的负载远远超过1,5,15分钟。

假设在一个空闲的系统上,开启一个单线程来跑CPU密集任务,60秒后的load averages是多少呢?如果load averages按普通平均值来算,这个值将是1.0。下面是一个绘制成图的实验结果

image

在上面的实验中,所谓的“1分钟load averages”在一分钟内只能达到0.62左右。

Linux不可中断任务

Linux中刚引入load averages时,和其他系统一样将其作为衡量CPU需求的指标,后来将其更改为不仅包含可运行任务,还包含处于不可中断状态的任务(TASK_UNINTERRUPTIBLE或nr_uninterruptible)。这种状态由希望避免信号中断的代码使用,其中包括阻塞在磁盘I/O和一些锁上的任务。在pstop的输出中,这种状态被标志为“D”。ps(1)的man page将其称为"不可中断睡眠状态(通常被IO阻塞)"

# man ps
.....
PROCESS STATE CODES
       Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the
       state of a process:

               D    uninterruptible sleep (usually IO)

...

为什么Linux中的load averages要加入不可中断状态,而不是像其他系统一样只计算CPU的需求呢?

加入不可中断的起源

oldlinux.org找到了一封1993年的邮件

From: Matthias Urlichs <urlichs@smurf.sub.org>
Subject: Load average broken ?
Date: Fri, 29 Oct 1993 11:37:23 +0200


The kernel only counts "runnable" processes when computing the load average.
I don't like that; the problem is that processes which are swapping or
waiting on "fast", i.e. noninterruptible, I/O, also consume resources.

It seems somewhat nonintuitive that the load average goes down when you
replace your fast swap disk with a slow swap disk...

Anyway, the following patch seems to make the load average much more
consistent WRT the subjective speed of the system. And, most important, the
load is still zero when nobody is doing anything. ;-)

--- kernel/sched.c.orig Fri Oct 29 10:31:11 1993
+++ kernel/sched.c  Fri Oct 29 10:32:51 1993
@@ -414,7 +414,9 @@
    unsigned long nr = 0;

    for(p = &LAST_TASK; p > &FIRST_TASK; --p)
-       if (*p && (*p)->state == TASK_RUNNING)
+       if (*p && ((*p)->state == TASK_RUNNING) ||
+                  (*p)->state == TASK_UNINTERRUPTIBLE) ||
+                  (*p)->state == TASK_SWAPPING))
            nr += FIXED_1;
    return nr;
 }
--
Matthias Urlichs        \ XLink-POP N|rnberg   | EMail: urlichs@smurf.sub.org
Schleiermacherstra_e 12  \  Unix+Linux+Mac     | Phone: ...please use email.
90491 N|rnberg (Germany)  \   Consulting+Networking+Programming+etc'ing      42

看到这么久之前的想法还是很令人惊叹的。

这也证明了Linux改变load averages的含义,使其不仅体现对CPU的需要,是有意的,这让load averages从“CPU负载均衡”变成了“系统负载均衡”。

邮件中举交换磁盘速度慢的例子是有道理的:通过降低系统性能,系统需求(运行和排队的进程数)应该增加;但是如果仅仅根据CPU运行状态,那么load averages值应该会下降。Matthias认为这是不直观的,所以修改了代码。

现代系统的不可中断

但是难道不会出现磁盘I/O不能解释Linux load averages过高的情况吗?这种情况是会出现的,这是因为在现代Linux(4.12)版本中,有将近400处代码设置了TASK_UNINTERRUPTIBLE状态,包括一些锁原语中。其中部分代码可能不需要统计在load averages中。

既然TASK_UNINTERRUPTIBLE在更多的地方被用到,那么是否应该将load averages改成只统计CPU和磁盘需求呢?Linux调度程序的维护者Peter Zijstra有一个想法:将TASK_UNINTERRUPTIBLE替换成task_struct->in_iowait,这样load averages就更贴近磁盘I/O的需求。这样又引入了另外一个问题,我们到底想要从load averages中得到什么?我们是需要用线程对系统的需求来衡量负载,还是只通过物理资源的使用情况来衡量负载呢?如果是前者的话,那么应该包含等待不间断锁的线程,因为这些线程并没有闲置。所以也许Linux的load averages已经按我们需要的方式工作了。

理解Linux的load averages

也许真正的问题在于“load averages”这个词和“I/O”一样含糊不清。到底是哪种I/O呢?是磁盘I/O?文件系统I/O?还是网络I/O。类似的,到底是哪种load averages呢?是CPU平均负载?还是系统平均负载?下面做一个总结吧:

  • 在Linux上,load averages的真实含义是“系统平均负载”,即对整个系统,测量正在工作并等待工作的线程数(CPU,磁盘,不可中断锁)。换句话说,这种方式测量的是不完全空闲的线程数量。这种方式的优势在于包括了对不同资源的需求
  • 在其他的系统上,load averages的含义是“CPU平均负载”,这组值用于测量正在占有CPU执行权的线程数量加上等待CPU的线程数量。

还有另一种可能的类型:“物理资源负载平均值”,其中包括仅用于物理资源(CPU+磁盘)的负载。

更精确的测量数据

当Linux的load averages值增加时,可以判断任务对系统资源(CPU,磁盘和锁)有了更高的需求,但是到底是对哪种资源的需求增长了呢?这时可以用其他的指标来进行判断。比如,CPU资源有如下指标:

  • 单个CPU使用率:可以用命令mpstat -P ALL 1查看
  • 每个进程的CPU使用率:可用命令toppidstat 1查看
  • 每个线程运行队列(调度程序)延迟:可用命令perf sched查看,也可以查看文件/proc/PID/schedstats
  • CPU运行队列延迟:可用命令perf sched查看,也可以查看文件/proc/schedstat
  • CPU运行队列长度:可用vmstat 1命令查看。

上面提供的指标中,前两个用来衡量使用率,后三个用来度量系统饱和度。利用率指标对于衡量工作负载很有用,而饱和度指标可用来识别性能问题。衡量CPU饱和度的最佳指标是运行队列(或调度程序)的延迟,延迟是指任务或者线程处于可运行状态,但必须等待CPU的时间。通过这样的指标可以用来衡量性能问题的严重程度,比如线程等待调度的时间在运行时间中占的百分比。通过观察运行队列长度可以很方便判断是否存在问题,但比较难定位到问题产生的原因。

schedstats功能在Linux 4.6中成为内核可调参数(sysctl.kernel.sched_schedstats),默认是关闭的。

尽管有更明确的指标,但并不意味着load averages是无用的。这组指标已经成功用于云计算微服务的扩展策略,微服务根据不同的负载值做出反应。有了这些判断的依据,即使在自动扩容时犯错也保险多了:扩容实例会花更多的钱,不扩容则会损失用户。如果扩容太多,后来调查一下纠正就是了。

总结

在1993年,一位Linux工程师发现了一个非直观的load averages情况,于是提交了三行代码的补丁将load averages的含义由“CPU负载平均值”变成了“系统负载平均值”。这次的变动在统计中包括了不可中断状态下的任务,所以load averages值不仅反映了对CPU的需求,还反映了对磁盘资源的需求。系统平均负载计算正在工作和等待工作的线程的数量,并且统计1分钟,5分钟,15分钟指数衰减的移动总和平均值。通过这三个值,能够知道系统的负载是在增加还是在减小。

Linux中对不可中断状态的使用越来越多,现在已经包括了不可中断的锁原语。如果需要衡量处于运行状态和等待状态的线程对于系统的需求,那么load averages依然是很好的指标。

最后引用kernel/sched/loadavg.c头部的注释来结束吧

  • This file contains the magic bits required to compute the global loadavg
  • figure. Its a silly number but people think its important. We go through
  • great pains to make it work on big machines and tickless kernels.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容