学习理解Linux系统负载


=Start=

缘由:

最近在写主机信息收集agent的时候发现很多之前没有考虑/注意到的知识点,系统负载就是其中一个(之前只是简单的知道服务器的平均负载越高,程序的运行耗时会越长,系统给人的感觉会越慢(真实情况也确实如此);服务器的平均负载越低,表明服务器的资源处于闲置状态的时间也越长,是一种资源浪费)。所以今天借着这个机会好好学习一下:系统负载的实际意义是什么?系统负载又是如何计算的?如何查看系统负载的情况?系统负载为多少时是正常、为多少时系统管理员又该注意了?

搜索关键字:
  • linux calc load
  • linux 负载 scoutapp
参考解答:
如何查看系统负载的情况?

究竟应该如何查看平均负载呢?最简单的命令是uptime:
[[email protected] ~]# uptime

还可以用w命令来查看,顺便可以查看一下系统当前有哪些用户,他们占用了哪些终端:
[[email protected] ~]# w

另外,还有动态命令top,这个命令也可以反映系统负载情况(第一行内容正是系统目前的负载情况):
[[email protected] ~]# top

另外还有一个最直接的显示系统平均负载的命令:
[[email protected] ~]# cat /proc/loadavg
0.10 0.06 0.01 1/72 29632

系统负载的实际意义是什么?

系统平均负载的基本解释:表示系统在过去一段时间(一般是1分钟、5分钟、15分钟)内进程队列中的平均进程数量

一个类比——行车过桥

假设你的电脑只有一个CPU,所有的运算都必须由这个CPU来完成。那么,我们不妨把这个CPU想象成一座大桥,桥上只有一根车道,所有车辆都必须从这根车道上通过。

系统负载为0,意味着大桥上一辆车也没有:

load_0

系统负载为0.5,意味着大桥一半的路段有车:

load_05

系统负载为1.0,意味着大桥的所有路段都有车,也就是说大桥已经”满”了。但是必须注意的是,直到此时大桥还是能顺畅通行的:

load_1

系统负载为1.7,意味着车辆太多了,大桥已经被占满了(100%),后面等着上桥的车辆为桥面车辆的70%:

load_17

以此类推,系统负载2.0,意味着等待上桥的车辆与桥面的车辆一样多;系统负载3.0,意味着等待上桥的车辆是桥面车辆的2倍。总之,当系统负载大于1,后面的车辆就必须等待了;系统负载越大,过桥就必须等得越久。

单CPU的系统负载,基本上等同于上面的类比。

如果CPU每分钟最多处理100个进程,那么系统负载0.2,意味着CPU在这1分钟里只处理20个进程;系统负载1.0,意味着CPU在这1分钟里正好处理100个进程;系统负载1.7,意味着除了CPU正在处理的100个进程以外,还有70个进程正排队等着CPU处理。

为了电脑顺畅运行,系统负载最好不要超过1.0,这样就没有进程需要等待了,所有进程都能第一时间得到处理。很显然,1.0是一个关键值,超过这个值,系统就不在最佳状态了,你要动手干预了。

对于多CPU来说,相当于有多个车道,系统可接受的最大合理负载也就翻了几倍。比如,2个CPU表明系统合理负载可以达到2.0,此时每个CPU都达到100%的工作量。推广开来,n个CPU的电脑,可接受的系统合理负载最大为n.0。

系统负载又是如何计算的?

Linux系统负载的计算是个复杂的过程,一般情况下直接用w/uptime等命令的输出就行,别自己计算了。下面截取一下从Wiki百科中看到的系统负载的计算公式:

unsigned long avenrun[3];

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);
   }
}

// The countdown is over a LOAD_FREQ of 5 Hz.

1 HZ = 100 ticks
5 HZ = 500 ticks
1 tick = 10 milliseconds
500 ticks = 5000 milliseconds (or 5 seconds)

// So, 5 HZ means that CALC_LOAD is called every 5 seconds.

// The avenrun array contains 1-minute, 5-minute and 15-minute average. The CALC_LOAD macro and its associated values are defined in sched.h :

#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;
系统负载为多少时是正常、为多少时系统管理员又该注意了?

看系统负载(对系统性能的影响)不能仅仅看它的数值大小,还需要根据服务器的CPU核心数量来进行判断。比如,当前系统有4个逻辑CPU,如果load average的三个值长期大于4时,说明CPU很繁忙,负载很高,可能会影响系统性能,但是偶尔大于4时,倒不用担心,一般不会影响系统性能。相反,如果load average的输出值小于CPU的个数,则表示CPU还有空闲。

如何得知我的系统装备了多少核心的处理器?在 Linux 下,可以使用命令:

$ cat /proc/cpuinfo

获取你系统上的每个处理器的信息。如果你只想得到数字,那么就使用下面的命令:

$ grep 'model name' /proc/cpuinfo | wc -l

一般情况下,单核平均负载在0.7以下是安全的,超过0.7就需要进行优化了。而且一般认为看负载情况看5分钟和15分钟的比较好。

单核负载是通过:

负载数值 / CPU核数

来估算的。

参考链接:

=EOF=

, ,

《“学习理解Linux系统负载”》 有 11 条评论

  1. Linux环境下进程的CPU占用率
    http://www.samirchen.com/linux-cpu-performance/
    `
    1、Linux 环境下查看 CPU 信息
    1.1、查看 CPU 详细信息
    1.2、查看多核 CPU 信息

    2、在 Linux 环境下计算进程的 CPU 占用
    2.1、通过 /proc/stat 文件查看所有的 CPU 活动信息
    2.2、通过 /proc/[PID]/stat 文件查看某一进程的 CPU 活动信息
    2.3、通过 /proc/[PID]/task/[TID]/stat 文件查看某一进程下的某一线程的活动信息

    2.4、单核情况下 CPU 使用率的计算
    2.4.1、基本思想
    2.4.2、计算总的 CPU 使用率 totalCPUUse
    2.4.3、计算某一进程的 CPU 使用率 processCPUUse
    2.4.4、计算某一线程的 CPU 使用率 threadCPUUse

    2.5、多核情况下 CPU 使用率的计算
    2.5.1、基本思想
    2.5.2、计算总的 CPU 使用率
    2.5.3、计算某一进程的 CPU 使用率 mProcessCPUUse
    2.5.4、计算某一线程的 CPU 使用率 mThreadCPUUse

    2.6、问题
    2.7、一个计算总的 CPU 占用率的小程序

    3、Linux 环境查看进程运行相关信息
    3.1、使用 ps 命令查看进程信息
    3.2、使用 top 命令查看进程信息
    `

  2. Linux环境下进程的CPU占用率
    http://www.samirchen.com/linux-cpu-performance/
    `
    进程cpu利用率计算方法:

    1、读取/proc/PID/stat文件:

    a、第13列(utime) + 第14列(stime) + 第15列(cutime) + 第16列(cstime) = procCpu1
    b、sleep 1s
    c、再次执行a步骤,计算得到procCpu2,进程这1s使用cpu时间为procCpu2-procCpu1

    2、读取/proc/stat文件

    获取这 一秒的总的cpu使用时间 totalCpuTime

    3、计算

    proc.cpu.percent = (procCpu2-procCpu1) *100.0 * 机器CPU核数 / totalCpuTime
    `

  3. 理解 CPU 利用率
    https://www.jianshu.com/p/f595ee986b55
    http://man7.org/linux/man-pages/man1/top.1.html

    `
    us, user: time running un-niced user processes

    sy, system: time running kernel processes

    ni, nice: time running niced user processes

    id, idle: time spent in the kernel idle handler

    wa, IO-wait: time waiting for I/O completion

    hi: time spent servicing hardware interrupts

    si: time spent servicing software interrupts

    st: time stolen from this vm by the hypervisor
    `

    当CPU很闲时,它在做什么?(What’s a CPU to do when it has nothing to do?)
    https://lwn.net/Articles/767630/

  4. CPU飙高,系统性能问题如何排查?
    https://mp.weixin.qq.com/s/fzLcAkYwKhj-9hgoVkTzaw
    `
    一、背景知识

    # LINUX进程状态

    LINUX 2.6以后的内核中,进程一般存在7种基础状态:D-不可中断睡眠(TASK_UNINTERRUPTIBLE)、R-可执行(TASK_RUNNING)、S-可中断睡眠(TASK_INTERRUPTIBLE)、T-暂停态(__TASK_STOPPED)、t-跟踪态(__TASK_TRACED)、X-死亡态(EXIT_DEAD)、Z-僵尸态(EXIT_ZOMBIE),这几种状态在PS命令中有对应解释。

    谈到系统性能,Load和CPU使用率是最直观的两个指标,那么这两个指标是怎么被计算出来的呢?是否能互相等价呢?
    不少人都认为,Load代表正在CPU上运行&等待运行的进程数,但Linux系统中,这种描述并不完全准确。

    从Linux内核源码中Load Average计算方法可以看出来,除了可执行态进程,不可中断睡眠态进程也会被一起纳入计算。在前文 Linux进程状态 中有提到过,不可中断睡眠态的进程(TASK_UNINTERRUTED)一般都在进行I/O等待,比如磁盘、网络或者其他外设等待。由此我们可以看出,Load Average在Linux中体现的是整体系统负载,即CPU负载 + Disk负载 + 网络负载 + 其余外设负载,并不能完全等同于CPU使用率(这种情况只出现在Linux中,其余系统比如Unix,Load还是只代表CPU负载)。

    # CPU使用率

    CPU的时间分片一般可分为4大类:用户进程运行时间 – User Time, 系统内核运行时间 – System Time, 空闲时间 – Idle Time, 被抢占时间 – Steal Time。除了Idle Time外,其余时间CPU都处于工作运行状态。

    通常而言,我们泛指的整体CPU使用率为User Time 和 Systime占比之和(例如tsar中CPU util)。为了便于定位问题,大多数性能统计工具都将这4类时间片进一步细化成了8类,如下为TOP对CPU时间片的分类。

    * us:用户进程空间中未改变过优先级的进程占用CPU百分比
    * sy:内核空间占用CPU百分比
    * ni:用户进程空间内改变过优先级的进程占用CPU百分比
    * id:空闲时间百分比
    * wa:空闲&等待I/O的时间百分比
    * hi:硬中断时间百分比
    * si:软中断时间百分比
    * st:虚拟化时被其余VM窃取时间百分比

    这8类分片中,除wa和id外,其余分片CPU都处于工作态。

    二、资源&瓶颈分析

    从上文我们了解到,Load Average和CPU使用率可被细分为不同的子域指标,指向不同的资源瓶颈。总体来说,指标与资源瓶颈的对应关系基本如下图所示。

    # Load高 & CPU高

    这是我们最常遇到的一类情况,即load上涨是CPU负载上升导致。根据CPU具体资源分配表现,可分为以下几类:

    ## CPU sys高

    这种情况CPU主要开销在于系统内核,可进一步查看上下文切换情况。

    * 如果非自愿上下文切换较多,说明CPU抢占较为激烈,大量进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。
    * 如果自愿上下文切换较多,说明可能存在I/O、内存等系统资源瓶颈,大量进程无法获取所需资源,导致的上下文切换。

    ## CPU si高

    这种情况CPU大量消耗在软中断,可进一步查看软中断类型。一般而言,网络I/O或者线程调度引起软中断最为常见:

    * NET_TX & NET_RX。NET_TX是发送网络数据包的软中断,NET_RX是接收网络数据包的软中断,这两种类型的软中断较高时,系统存在网络I/O瓶颈可能性较大。
    * SCHED。SCHED为进程调度以及负载均衡引起的中断,这种中断出现较多时,系统存在较多进程切换,一般与非自愿上下文切换高同时出现,可能存在CPU瓶颈。

    ## CPU us高

    这种情况说明资源主要消耗在应用进程,可能引发的原因有以下几类:

    * 死循环或代码中存在CPU密集计算。这种情况多核CPU us会同时上涨。
    * 内存问题,导致大量FULLGC,阻塞线程。这种情况一般只有一核CPU us上涨。
    * 资源等待造成线程池满,连带引发CPU上涨。这种情况下,线程池满等异常会同时出现。

    # Load高 & CPU低

    这种情况出现的根本原因在于不可中断睡眠态(TASK_UNINTERRUPTIBLE)进程数较多,即CPU负载不高,但I/O负载较高。可进一步定位是磁盘I/O还是网络I/O导致。

    三、排查策略

    从问题发现到最终定位,基本可分为四个阶段:

    1. 资源瓶颈定位(top、vmstat、tsar(历史))

    这一阶段通过全局性能检测工具,初步定位资源消耗异常位点。

    2. 热点进程定位(iotop、pidstat、ps)

    定位到资源瓶颈后,可进一步分析具体进程资源消耗情况,找到热点进程。

    3. 线程&进程内部资源定位(pidstat、lsof)

    找到具体进程后,可细化分析进程内部资源开销情况。

    4. 热点事件&方法分析(perf、jstack、strace、tcpdump)

    获取到热点线程后,我们可用trace或者dump工具,将线程反向关联,将问题范围定位到具体方法&堆栈。
    `

  5. 对cpu与load的理解及线上问题处理思路解读
    https://mp.weixin.qq.com/s/ENGcqDABD9TLD6gjM0Jegw
    `
    既然说了cpu和load,那总需要监控吧,没有监控就不知道cpu和load,后面的一切也就无从谈起了。

    top命令是最常见的查看cpu和load的命令,做了一张表格比较详细地解释了每一部分的含义,其中重要属性做了标红加粗:

    top – 20:36:26 up 748 days, 2:46, 1 user, load average: 0.05, 0.10, 0.13
    Tasks: 739 total, 1 running, 736 sleeping, 2 stopped, 0 zombie
    %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
    KiB Mem : 13112350+total, 3815568 free, 14659264 used, 11264867+buff/cache
    KiB Swap: 0 total, 0 free, 0 used. 10999672+avail Mem

    第一行 距离上次系统启动时间差了2分46秒,当前有1个用户在登录,最近1/5/15分钟系统的平均负载
    第二行 当前总共有 739 个进程,有 1 个正在运行的进程,736 个进程处于休眠状态,2 个处于停止状态,0 个进程处于僵尸状态

    第三行 所有CPU的总体信息,【此时按1会切换到查看每个CPU信息的界面(再按1即可返回)】,后面的参数都一样
    0.0 us 用户空间占用CPU的百分比
    0.0 sy 内核空间占用CPU的百分比
    0.0 ni 改变过优先级的进程占CPU的百分比
    99.9 id 空闲CPU的百分比
    0.0 wa 磁盘IO等待占CPU的百分比
    0.0 hi 硬中新上CPI的百分比
    0.0 si 软中断占CPU的百分比
    0.0 st 虚拟CPU占CPU的百分比

    第四行(内存)第五行(SWAP分区)
    13112350+ total 物理内存总量,单位为字节
    3815568 free 空闲内存总量。 单位为字节
    14659264 used 使用中的内存总量,单位为字节
    11264867+ buf/cache 缓存的内存总量,单位为字节

    # load高、cpu高的问题排查思路

    首先抛出一个观点:cpu高不是问题,由cpu高引起的load高才是问题,load是判断系统能力指标的依据。

    # load高、cpu低的问题排查思路
    关于load的部分,我们可以看到会导致load高的几个因素:
    * 线程正在使用cpu
    * 线程正在等待使用cpu
    * 线程在执行不可被打断的IO操作

    # Java应用load高的几种原因总结
    前面说了这么多,这里总结一下load高可能的一些原因:
    * 死循环或者不合理的大量循环操作,如果不是循环操作,按照现代cpu的处理速度来说处理一大段代码也就一会会儿的事,基本对能力无消耗
    * 频繁的YoungGC
    * 频繁的FullGC
    * 高磁盘IO
    * 高网络IO

    系统load高通常都是由于某段发布的代码有bug或者引入某些第三方jar而又使用不合理导致的,因此注意首先区分load高,是由于cpu高导致的还是io高导致的,根据不同的场景采取不同定位问题的方式。
    当束手无策时,jstack打印堆栈多分析分析吧,或许能灵光一现能找到错误原因。

    # 结语
    先有理论,把理论想透了,实战碰到问题的时候才能头脑清楚。

    坦白讲,cpu和load高排查是一个很偏实战的事情,这方面我还也有很长一条路需要走,身边在这块经验比我丰富的同事多得很。很多人有问过我,项目比较简单,根本没有这种线上问题需要我去排查怎么办?这个问题只能说,平时多积累、多实战是唯一途径,假如没有实战机会,那么推荐三种方式:
    * 自己通过代码模拟各种异常,例如FullGC、死锁、死循环,然后利用工具去查,可能比较简单,但是万丈高楼平地起,再复杂的东西都是由简单的变化过来的
    * 多上服务器上敲敲top、sar、iostat这些命令,熟记每个命令的作用及输出参数的含义
    * 去网上找一下其他人处理FullGC、CPU高方法的文章,站在巨人的肩膀上,看看前人走过的路,总结记录一些实用的点

    当真的有实战机会来的时候把握住,即使是同事排查的问题,也可以在事后搞清楚问题的来龙去脉,久而久之自然这方面的能力就会提高上去。
    `

  6. 一文带你全面了解 Load Average (负载)
    https://mp.weixin.qq.com/s/qqimEIOKjMJe7DHyXT09fA
    `
    1、什么是 load average?

    2、如何查看 load average?

    3、对负载的理解

    4、实际运维工作的指导意义

    测试场景1:对不同核数的机器施加同样的压力
    结论:
    1、同等压力下,不论核数多少,load average数值是一样的,但是cpu idle 不一样,核数多的机器空闲率高,可以承载更多的计算任务。
    2、单线程任务只会使用一个CPU,不管CPU核数有多少。

    测试场景2:对同一台机器增加一倍的压力
    结论:
    1、对于相同的机器,压力增大一倍,load average 相应增大一倍;
    从理论上来讲,让load average 保持在 “load average数字/CPU核数”, 在0.00-1.00之间,表示CPU处于高利用率而又不是负载过高,是较为理想的值;
    多核CPU,满负荷状态的数字为 “1.00 * CPU核数”,即双核CPU为2.00,四核CPU为4.00。
    2、再次印证:单线程任务只会使用一个CPU,不管CPU核数有多少。

    测试场景3:对同样的机器,运行单线程和多线程程序

    5、Load Average在故障排查时的运用

    实际工作中,经常会遇到服务响应慢的问题,如果熟悉Load Average和CPU、IO之间的关系,一般可以快速定位问题。

    # 5.1、状态为R和D的任务

    状态为R,表示正在运行,或者处于运行队列,可以被调度运行。
    状态为D,表示 uninterruptible sleep,这种状态是不可中断的,无论是kill,kill -9,还是kill -15。

    处于D状态的进程通常是在等待IO,比如磁盘 IO,网络 IO,其他外设 IO。
    如果处于D状态的时间较长,意味着可能是IO设备本身出了故障,需要排查设备是否正常。

    # 5.2、CPU使用率高,IO无作业,Load Average低,系统反应颠簸

    这种场景,通常是计算密集型任务,即大量生成耗时短的计算任务。
    这种任务会占满CPU资源,造成系统响应速度颠簸,但由于每个任务能快速计算完成,不会在运行队列堆积,所以在Load Average里不会体现出来。

    # 5.3、CPU使用率低,IO等待,Load Average高,系统不卡

    Load Average高,dd程序都处于D状态
    示例命令,大量写小文件: dd if=/dev/zero of=testx.img bs=512count=1000000 oflag=dsync

    这种场景,通常是IO密集型任务,如果大量请求都集中于相同的IO设备,超出设备的响应能力,会造成任务在运行队列里堆积等待,也就是D状态的进程堆积,那么此时Load Average就会飙高。

    由于任务都处于等待状态,所以Load Average的值虽然很高,但系统响应速度不受影响。

    # 5.4、CPU使用率低,IO繁忙,Load Average低,系统卡

    这种场景,通常是低频大文件读写,由于请求数量不大,所以任务都处于R状态,Load Average数值反映了当前运行的任务数,不会飙升,IO设备处于满负荷工作状态,导致系统响应能力降低。

    # 5.5、CPU使用率高,IO繁忙/等待,Load Average高,系统卡

    这种场景,通常是服务混部,即IO、计算密集型任务混部在一起,相当于CPU、IO都处于高负荷状态,那么Load Average 自然很高。
    `

  7. […] 前段时间因为部分工作内容涉及到Linux系统的CPU、内存资源占用分析,所以简要回顾了一下之前整理的文章,内容其实没啥大问题,但太简单和基本,只是简单介绍了一下系统负载的概念以及查看方法,缺少了具体场景下的分析思路和方法,没有什么实际的指导意义,所以近期又通过搜索找到了一批不错的文章(主要是 CPU飙高,系统性能问题如何排查? 和 一文带你全面了解 Load Average (负载) 这两篇)进行学习,以期能够解答我的一些疑问,同时方便后面有需要的时候进一步参考。 […]

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注