萍乡市网站建设_网站建设公司_SSG_seo优化
2025/12/27 20:35:21 网站建设 项目流程

Linux 中的 Load Average

在 Linux 系统中,Load Averages 通常指的是 system load averages,可以通过 uptime 命令查看:

$ uptime
09:41:46 up 60 days, 15:05, 16 users,  load average: 17.28, 16.55, 17.00

这三个数值分别表示系统在 过去 1 分钟、5 分钟和 15 分钟 内的平均负载。

除了 uptime,也可以直接读取 /proc/loadavg 文件来获取同样的信息。


Load Average 是如何计算的

Load average 经常被误认为是 CPU 使用率。在某些操作系统中确实如此,但 Linux 的 load average 并不等同于 CPU load

在 Linux 中,load average 的统计来源主要包括两部分:

  1. 处于就绪队列(R 状态)的进程
    表示正在运行或等待 CPU 的进程,反映了对 CPU 的需求。
  2. 处于不可中断睡眠(D 状态)的进程
    通常表示在等待磁盘 IO、块设备或某些内核资源。

因此,Linux 的 load average 实际上反映的是:

系统中“需要 CPU 或无法继续运行”的进程数量的变化趋势


指数平滑算法

内核在计算平均负载时,并不是简单地求平均值,而是使用了 指数加权移动平均(Exponential Moving Average, EMA)

计算公式为:

\[load_{new} = load_{old} \times \alpha + active \times (1 - \alpha) \]

其中:

\[\alpha = e^{-1/n}, \quad n = T / \Delta T \]

  • active:当前采样周期内处于 R/D 状态的进程数
  • ΔT:采样间隔(Linux 中为 5 秒)
  • T:统计窗口时间(1 分钟、5 分钟、15 分钟)

例如:
如果采样间隔为 5 秒,窗口为 60 秒,则 n = 12


Linux 内核实现

Linux 内核中对应的实现如下(kernel/sched/loadavg.c):

#define FSHIFT		11		/* nr of bits of precision */
#define FIXED_1		(1<<FSHIFT)	/* 1.0 as fixed-point */
#define LOAD_FREQ	(5*HZ+1)	/* 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) *//** a1 = a0 * e + a * (1 - e)*/
static inline unsigned long
calc_load(unsigned long load, unsigned long exp, unsigned long active)
{unsigned long newload;newload = load * exp + active * (FIXED_1 - exp);if (active >= load)newload += FIXED_1 - 1;return newload / FIXED_1;
}

由于内核无法直接使用浮点运算,上述代码通过 定点数(fixed-point) 来模拟浮点计算。
例如:

#define FSHIFT		11
#define FIXED_1		(1<<FSHIFT)

表示用 11 位小数来保存精度。

EXP_1EXP_5EXP_15 分别对应 1 分钟、5 分钟和 15 分钟窗口的指数衰减因子。

该计算逻辑由全局定时器周期性触发调用:
https://elixir.bootlin.com/linux/v6.18.2/source/kernel/sched/loadavg.c#L351


Load Average 有什么意义

Load average 非常适合用来观察 系统负载随时间的变化趋势

  • load average 为 0
    系统完全空闲
  • 1 分钟 > 5 分钟 > 15 分钟
    系统负载正在上升
  • 1 分钟 < 5 分钟 < 15 分钟
    系统负载正在下降
  • load average 长期高于 CPU 核心数
    可能存在性能瓶颈(但并非绝对)

为什么 Load Average 会升高

根据 Brendan Gregg 对 load average 演进历史的分析,Linux 最初只统计对 CPU 的需求,后来为了反映 磁盘 IO 对系统响应性的影响,引入了对 D 状态进程的统计。

需要注意的是,D 状态并不只来自磁盘 IO,例如:

  • 等待块设备 IO
  • 获取内核锁(如 rwsem_down_read_failed
  • 某些驱动或文件系统操作

因此,load average 升高可能意味着:

  1. 大量进程正在消耗 CPU
  2. 大量进程在等待 IO
  3. 大量进程在内核中阻塞(锁竞争等)

如何进一步排查 Load Average 升高的原因

可以从以下几个维度进行分析:

  • 每 CPU 利用率
    • mpstat -P ALL 1
  • 进程 / 线程 CPU 使用情况:
    • top
    • pidstat 1
  • 线程调度延迟(run queue latency)
    • /proc/PID/schedstats
    • delaystats
    • perf sched
  • CPU run queue 延迟
    • /proc/schedstat
    • perf sched
    • runqlat(BCC)
  • CPU run queue 长度
    • vmstat 1r
    • runqlen(BCC)

参考资料

  1. https://www.codedump.info/post/20200620-sgfap-loadavg/
  2. https://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询