04CPU使用率分析-Linux性能优化

节拍率

  • 为了维护CPU时间,Linux通过事先定义的节拍率(内核中表示HZ)来触发时间中断,并使用全局变量Jiffies来记录开机以后的节拍次数。每发生一次时间中断,jiffies的值就加1.
  • 节拍率HZ是内核的可配置参数,可以设置为100、250、1000等。而用户空间的节拍率USER_HZ固定为100,你可以通过/boot/config内核选项来查看。

    1
    grep 'CONFIG_HZ' /boot/config-$(uname -r)
  • 以下展示率各个CPU的节拍率,一般性能分析工具给出的都是间隔一段时间的平均CPU使用率,比如top是每隔3秒的平均值,PS使用的是整个进程的生命周期。

    1
    2
    3
    4
    5
    6
    # 只保留各个 CPU 的数据
    $ cat /proc/stat | grep ^cpu
    # 第一行表示的是所有CPU的累加,其他则是不同场景下CPU的累加节拍数,单位是USER_HZ(1/100秒)
    cpu 280580 7407 286084 172900810 83602 0 583 0 0 0
    cpu0 144745 4181 176701 86423902 52076 0 301 0 0 0
    cpu1 135834 3226 109383 86476907 31525 0 282 0 0 0

CPU使用率高如何定位?

  • 通过top、ps、pidstat定位具体是哪个进程的CPU高,是内核态还是用户态占用高。那如果找到了哪个进程占用CPU高,那如何定位到是哪个函数占用CPU高呢?
  • 我们一般不建议直接在线上环境使用GDB或者STRACE命令,毕竟会临时中断程序,那么我们可以使用perf命令来分析,工具安装:

    1
    2
    #perf工具安装
    sudo apt install linux-tools-common
  • perf top命令类似于top,它能够实时显示占用CPU时钟最多的函数或者指令,用来查找热点函数,如下界面:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ 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

    #如果采用太少,比如几十个的话,参考意义不大。
    #第一行包含三个数据,分别是采样数(Samples)、事件类型(event)、时间总数量(Event count),这个例子中perf总共采集了833个CPU时钟事件、总事件数则为97742399。
    #第一列Overhead:代表该符合的性能事件在所有采用中的比例,用百分比表示。
    #第二列Shared:该函数或者指令所在的动态共享对象,如内核、进程名、动态链接库名、内核模块等。
    #第三列Object:动态共享对象的类型,比如[.]代表用户空间的可执行程序或者动态链接库,而[k]则表示内核空间。
    #第四列Symbol:符号名,也就是函数名,当函数名未知时,用十六进制的地址表示。
  • perf top不能离线分析,我们可以使用perf record top -g -p pid来进行采用,-g参数开启调用关系采用,在report中按方向键选中并回车可看到调用关系。

    1
    2
    3
    4
    $ perf record # 按 Ctrl+C 终止采样
    [ perf record: Woken up 1 times to write data ]
    [ perf record: Captured and wrote 0.452 MB perf.data (6093 samples) ]
    $ perf report # 展示类似于 perf top 的报告

如果找不到哪个进程CPU使用率高?

  • 碰到无法解释的CPU使用率情况时,首先要想到有可能是短时应用导致的问题,比如有下面2情况:
    • 应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过top等工具不容易发现。
    • 应用本身在不停地奔溃重启,而启动过程地资源初始化,很可能会占用相当多地CPU。
  • 对于这种情况,我们可以用pstree或者execsnoop找到它们地父进程,再从父进程所在应用入手,排查问题。

小结

  • 用户CPU和Nice CPU高,说明用户态进程占用CPU高,所以重点排查进程的性能问题。
  • 系统CPU高,说明内核态占用CPU高,应重点排查内核线程或者系统调用的性能问题。
  • I/O等待CPU高,说明等待I/O的时间比较长,应该重点排查系统存储是否有瓶颈。
  • 软中断或者硬中断高,说明软中断或者硬中断处理程序占用CPU高,应该重点排查内核的中断服务程序。
-------------本文结束感谢您的阅读-------------