CPU的使用率和负载的区别

0x01 CPU使用率

这个比较好理解,先来说说这个概念。使用率其实也就是一段时间内 使用时间/总时间

直接说CPU的使用率计算方式吧:

CPU在t1和t2时间内的使用率=CPU非空闲时间/CPU总时间*100%=(1-CPU的空闲时间/CPU总时间)*100%

很好理解。比如一个单核CPU,你程序写个死循环,然后很容易把CPU跑到接近100%,因为死循环不会让出时间片,就会一直占用CPU
比如:http://ju.outofmemory.cn/entry/23059

0x02 CPU负载

计算方式

或许你可能已经看了其他的一些博客,里面多数是cpu load比喻成电话亭打电话、大桥上通车等。这个的确很形象,但是却并不准确。因为Linux系统并不是这样简单的计算。并不是简单的平均
CPU Load的计算是使用到了统计学中指数移动平均(英语:exponential moving average,EMA或EXMA)的概念。
为啥这样?因为:

  • 移动平均可抚平短期波动,反映出长期趋势或周期。数学上,移动平均可视为一种卷积。
  • 各数值的加权影响力随时间而指数式递减,越近期的数据加权影响力越重,但较旧的数据也给予一定的加权值。

总结一下就是这个统计算法不仅考虑了短期也能反映长期趋势,不仅计算了近期的值还考虑的旧的数据。

Linux中具体计算方式代码如下:
calc_load一般是5*Hz就调用一次,(Hz variable is the pulse rate of particular Linux kernel activity,默认值是10ms)

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

真正的计算公式:

#define FSHIFT   11		/* nr of bits of precision */
#define FIXED_1  (1<>= FSHIFT;

cpu load的确能够反映出某时间段内活跃进程的量。
函数如下:

/*
 * Either called from update_cpu_load() or from a cpu going idle
 */
static void calc_load_account_active(struct rq *this_rq)
{
	long nr_active, delta;

	nr_active = this_rq->nr_running;  //记录在cpu上运行的进程数
	nr_active += (long) this_rq->nr_uninterruptible;  //记录不可中断的进程数

	if (nr_active != this_rq->calc_load_active) {
		delta = nr_active - this_rq->calc_load_active;
		this_rq->calc_load_active = nr_active;
		atomic_long_add(delta, &calc_load_tasks);
	}
}

上面函数需要注意:
(直接引用参考里面的话)

  • 大多数的Unix系统中的负载只是记录那些处在运行状态和可运行状态的进程,但是Linux有所不同,它会包含那些不可中断的处于睡眠状态的进程。这时当这些进程由于I/O的阻塞而不能够运行,就可能显著的增加cpu的负载。所以在Unix和Linux下的cpu的负载的计算方法是不一样的,在设定监测值的时候也需要特别考率。
  • Linux记录cpu负载的时候是将cpu队列中的运行进程数和不可中断进程数都统计在内的,这样在对cpu负载分析的时候就需要考虑不可中断的进程的情况

所以这个函数才是重点啊:在分析机器负载过高的时候,除了需要关注那些活跃的进程,还需要关注那些由于I/O的阻塞变成不可中断状态的进程。很多时候机器负载突然飙升可能就是IO引起的。
至于load的算法了解就行。

另外插入介绍一下上面说的不可中断进程:
(我觉得这个说的比较好,https://cloud.tencent.com/developer/news/376204)

所谓不可中断sleep是指不能立刻响应处理一些信号的sleep进程,唯一可以唤醒进程的只能是一些等待的资源变得可用(如I/O)或者是等待的时间超时(如果超时时间在进程被置为sleep时已经指定)。
不可中断的sleep通常都由设备驱动程序用来等待磁盘或者网络I/O。该进程从系统调用或陷阱中返回后会收到在其sleep期间累积的信号。在Linux系统中ps -l指令使用字母D来表示不可中断sleep的状态。

这个状态一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。kill -9 也无法杀死

负载值大小

一个CPU满负载其值应该是1,超过1就是过载,低于1一般也没啥压力
n个CPU满负载其值应该是n,超过n就是过载,低于n一般没啥压力

机器过载的话,一般就变得很卡,基本都会影响到上面的服务了,要很重视。

0x03 负载和使用率

  1. 高cpu使用率时,负载不一定很高
    一个机器48个核如果全100%的使用率,那么整个机器使用率是100%,但是负载也可能只是48刚好满负载而已。

  2. 高负载的时候,cpu使用率不一定高
    可能由于多个进程运行不可中断的IO,导致活跃进程数量增加,这个时候负载会飚的很高,但是cpu可能很低

0x04 举个栗子

(高负载,低IO的)
机器配置是48核的。
下图是出问题的机器,负载突然变成1000多。吓死个人,但是CPU就30多
在这里插入图片描述
一套军体拳:iostat, sar, demsg, mpstat, pidstat, free, vmstat
发现磁盘IO最高也就200MB/s,并不高并没有到瓶颈,网络IO也不高,机器是万兆网卡。最后通过vmstat 发现了端倪,见下图。
在这里插入图片描述

r:表示运行和等待CPU时间片的进程数

可以看见已经很高了,爆表了。

而正常的机器上是这个样的:
CPU的使用率和负载的区别_第1张图片
在这里插入图片描述
后来在出问题的机器上ps -ef一看发现有好几百个同样的脚本再跑,而这个脚本里面有这么一段:

find / -name ""

OK!,问题找到。本来只需要一个这样的脚本跑。其他的都杀了

可以看见run
参考:
cpu使用率
1 http://www.voidcn.com/article/p-yqnvtups-xu.html
cpu负载
2 https://en.wikipedia.org/wiki/Load_%28computing%29#cite_note-5
3 https://zh.wikipedia.org/wiki/%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87
4 https://github.com/autowebkit/tech/wiki/CPU%E8%B4%9F%E8%BD%BD
5 http://einverne.github.io/post/2019/03/cpu-load.html
6 https://lotabout.me/2018/how-system-load-is-calculated/
如何处理不可中断进程
https://www.cnblogs.com/xiaowenshu/p/10477591.html

你可能感兴趣的:(Linux/Shell,操作系统,CPU使用率,CPU负载)