• Linux-CPU之平均负载


    一般我们觉得系统变慢了,都会执行 top 或者 uptime 命令,来了解系统的负载情况。

     uptime
     11:29:06 up 0 min,  2 users,  load average: 1.21, 0.29, 0.10
     // 当前时间    // 系统运行时间  // 正在登录用户数   //1 分钟、5 分钟、15 分钟的平均负载
    
    • 1
    • 2
    • 3

    概念:

    平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。

    1. 可运行状态的进程,是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。
    2. 不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的。比如最常见的是等待硬件设备的 I/O 响应,也就是我们在 ps 命令中看到的 D 状态(Uninterruptible Sleep,也称为 Disk Sleep)的进程。

    平均负载多少合适

    本质:平均负载其实就是平均活跃进程数。

    理想的,就是每个 CPU 上都刚好运行着一个进程,这样每个 CPU 都得到了充分利用。

    当平均负载高于 CPU 数量 70% 的时候,你就应该分析排查负载高的问题了。

    平均负载为 2 时:
    只有 2 个 CPU 的系统上,意味着所有的 CPU 都刚好被完全占用。
    4 个 CPU 的系统上,意味着 CPU 有 50% 的空闲。
    1 个 CPU 的系统中,则意味着有一半的进程竞争不到 CPU。

    如何获取CPU的个数:文件 /proc/cpuinfo 中获取个数。

    grep 'model name' /proc/cpuinfo |wc -l
    2
    
    • 1
    • 2

    平均负载与 CPU 使用率区分

    平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数,不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。

    CPU 使用率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应。

    CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
    I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
    大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。

    CPU 使用率

    Linux 作为一个多任务操作系统,将每个 CPU 的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用。

    维护 CPU 时间,Linux 通过事先定义的节拍率(内核中表示为 HZ),触发时间中断,并使用全局变量 Jiffies 记录了开机以来的节拍数。每发生一次时间中断,Jiffies 的值就加 1。

    因为节拍率 HZ 是内核选项,为了方便用户空间程序,内核还提供了一个用户空间节拍率 USER_HZ,它总是固定为 100,也就是 1/100 秒。

    Linux 通过 /proc 虚拟文件系统,向用户空间提供了系统内部状态的信息,而 /proc/stat 提供的就是系统的 CPU 和任务统计信息。

    cat /proc/stat
    //user 用户态时间nice 用户态时间(低优先级,nice>0)
    //system 内核态时间  idle 空闲时间
    //iowait I/O等待时间
    //irq 硬中断  softirq 软中断
    
    //CPU指标:user,nice, system, idle, iowait, irq, softirq
    cpu  130216 19944 162525 1491240 3784 24749 17773 0 0 0
    cpu0 40321 11452 49784 403099 2615 6076 6748 0 0 0
    cpu1 26585 2425 36639 151166 404 2533 3541 0 0 0
    cpu2 22555 2957 31482 152460 330 2236 2473 0 0 0
    cpu3 15232 1243 20945 153740 303 1985 3432 0 0 0
    cpu4 5903 595 6017 157410 30 10959 605 0 0 0
    cpu5 4716 380 3794 157909 23 118 181 0 0 0
    cpu6 8001 515 8995 157571 48 571 180 0 0 0
    cpu7 6903 377 4869 157885 31 271 613 0 0 0
    
    intr ...   //系统启动以来的所有interrupts的次数情况
    ctxt 22523049  //系统上下文切换次数
    btime 1500827856  //启动时长(单位:秒),从Epoch(即1970零时)开始到系统启动所经过的时长,每次启动会改变。
    processes 23231  //系统启动后所创建过的进程数量。当短时间该值特别大,系统可能出现异常
    procs_running 1  // 处于Runnable状态的进程个数
    procs_blocked 0  // 处于等待I/O完成的进程个数
    softirq 3552900 843593 733695 19691 93143 468832 12783 257382 610426 0 513355
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    时间单位,sysconf(_SC_CLK_TCK)一般地定义为jiffies(一般地等于10ms)

    iowait时间是不可靠值,理由如下:
    CPU不会等待I/O执行完成,而iowait是等待I/O完成的时间。 当CPU进入idle状态,很可能会调度另一个task执行,所以iowait计算时间偏小;

    计算方法

    在这里插入图片描述
    根据这个公式,我们就可以从 /proc/stat 中的数据,很容易地计算出 CPU 使用率。当然,也可以用每一个场景的 CPU 时间,除以总的 CPU 时间,计算出每个场景的 CPU 使用率。

    这是开机以来的节拍数累加值,所以直接算出来的,是开机以来的平均 CPU 使用率,一般没啥参考价值。

    为了计算 CPU 使用率,性能工具一般都会取间隔一段时间(比如 3 秒)的两次值,作差后,再计算出这段时间内的平均 CPU 使用率,即
    在这里插入图片描述

    top 默认使用 3 秒时间间隔,而 ps 使用的却是进程的整个生命周期。

    CPU 使用率过高排查

    1.通过 top、ps、pidstat 等工具,你能够轻松找到 CPU 使用率较高(比如 100% )的进程。
    2.寻找占用 CPU 的到底是代码里的哪个函数呢。

    perf:perf 是 Linux 2.6.31 以后内置的性能分析工具。它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。

    $ perf top
    Samples: 833  of event 'cpu-clock', Event count (approx.): 97742399
    Overhead  Shared Object       Symbol
       7.28%  perf                [.] 0x00000000001f78a4
       4.72%  [kernel]            [k] vsnprintf
       4.32%  [kernel]            [k] module_get_kallsym
       3.65%  [kernel]            [k] _raw_spin_unlock_irqrestore
    ...
    
    #离线采集分析   -g 参数,开启调用关系的采样
    perf record -g # 按 Ctrl+C 终止采样
    perf report # 展示类似于 perf top 的报告
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    第一行包含三个数据,分别是采样数(Samples)、事件类型(event)和事件总数量(Event count)。比如这个例子中,perf 总共采集了 833 个 CPU 时钟事件,而总事件数则为 97742399。

    第一列 Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示。
    第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
    第三列 Object ,是动态共享对象的类型。比如 [.] 表示用户空间的可执行程序、或者动态链接库,而 [k] 则表示内核空间。
    最后一列 Symbol 是符号名,也就是函数名。当函数名未知时,用十六进制的地址来表示。

  • 相关阅读:
    Qt creator下载安装
    密码学 | 承诺:绑定性 + 隐藏性
    CSS中的浮动float(元素怎样浮动以及浮动元素的特点--脱标)
    【檀越剑指大厂--泛型】泛型总结
    JavaWeb三层架构
    生产事故-走近科学之消失的JWT
    Learn Prompt-人工智能基础
    Java 流处理之收集器
    [游戏开发][Unity]安卓出包报错记录
    黑马点评项目Redis实现分布式锁
  • 原文地址:https://blog.csdn.net/weixin_45370502/article/details/128170573