什么是 CPU 使用率

CPU 使用率是单位时间内 CPU 使用情况的统计,以百分比的方式展示,我们通常所说的 CPU 使用率,就是除了空闲时间外的其他时间占总 CPU 时间的百分比

怎么查看 CPU 使用率

top 和 ps 是最常用的性能分析工具:top 显示了系统总体的 CPU 和内存使用情况,以及各个进程的资源使用情况。ps 则只显示了每个进程的资源使用情况。

top 默认每 3 秒刷新一次,输出格式为:

top - 21:12:50 up 21 days, 23:13,  2 users,  load average: 0.05, 0.04, 0.01
Tasks: 125 total,   2 running, 123 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.7 us,  0.3 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  4042140 total,  1991136 free,   140000 used,  1911004 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  3576656 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1011 ubuntu    20   0   40492   3696   3152 R   0.3  0.1   0:00.02 top
    1 root      20   0  119960   6116   4020 S   0.0  0.2   2:38.76 systemd
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kthreadd
    3 root      20   0       0      0      0 S   0.0  0.0   0:25.69 ksoftirqd/0
    5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
    7 root      20   0       0      0      0 S   0.0  0.0   3:57.57 rcu_sched
    8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh
    9 root      rt   0       0      0      0 S   0.0  0.0   0:10.86 migration/0
   10 root      rt   0       0      0      0 S   0.0  0.0   0:06.89 watchdog/0
   11 root      rt   0       0      0      0 S   0.0  0.0   0:05.72 watchdog/1
   12 root      rt   0       0      0      0 S   0.0  0.0   0:12.66 migration/1

输出结果中,第三行 %Cpu 就是系统的 CPU 使用率,只是把 CPU 时间变换成了 CPU 使用率,不过需要注意,top 默认显示的是所有 CPU 的平均值,这个时候你只需要按下数字 1 ,就可以切换到每个 CPU 的使用率了。

空白行之后是进程的实时信息,每个进程都有一个 %CPU 列,表示进程的 CPU 使用率。它是用户态和内核态 CPU 使用率的总和,包括进程用户空间使用的 CPU、通过系统调用执行的内核空间 CPU 、以及在就绪队列等待运行的 CPU。在虚拟化环境中,它还包括了运行虚拟机占用的 CPU。

top 并没有细分进程的用户态 CPU 和内核态 CPU,需要查看每个进程的详细情况,可以用 pidstat ,它正是一个专门分析每个进程 CPU 使用情况的工具。

下面的 pidstat 命令,就间隔 1 秒展示了进程的 5 组 CPU 使用率,包括:

  • 用户态 CPU 使用率(%usr)

  • 内核态 CPU 使用率(%system)

  • 运行虚拟机 CPU 使用率(%guest)

  • 等待 CPU 使用率(%wait)

  • 以及总的 CPU 使用率(%CPU)

最后的 Average 部分,还计算了 5 组数据的平均值。

pidstat 1 5 #每隔 1 秒输出一组数据,共输出 5 组
Linux 4.4.0-142-generic (10-53-166-171)     07/03/2019     _x86_64_    (2 CPU)

09:22:18 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command

09:22:19 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
09:22:20 PM  1000      2093    0.00    1.00    0.00    1.00     1  pidstat
09:22:20 PM   113      4606    1.00    0.00    0.00    1.00     0  beam.smp

09:22:20 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
09:22:21 PM   113      4606    0.00    1.00    0.00    1.00     0  beam.smp

09:22:21 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
09:22:22 PM  1000      2093    0.00    1.00    0.00    1.00     1  pidstat

09:22:22 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command

Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
Average:     1000      2093    0.00    0.40    0.00    0.40     -  pidstat
Average:      113      4606    0.20    0.20    0.00    0.40     -  beam.smp

CPU 使用率过高怎么办

通过 top、ps、pidstat 等工具,你能够轻松找到 CPU 使用率较高(比如 100% )的进程,如果需要排查占用 CPU 的到底是代码里的哪个函数,推荐使用 perf。perf 是 Linux 2.6.31 以后内置的性能分析工具。它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。

perf 分析 CPU 性能问题,两种最常见用法

第一种

perf top,类似于 top,它能够实时显示占用 CPU 时钟最多的函数或 者指令,因此可以用来查找热点函数,使用界面如下所示:

sudo perf top
Samples: 674  of event 'cpu-clock', Event count (approx.): 149937500
Overhead  Shared Object            Symbol
   9.48%  [kernel]                 [k] vsnprintf
   8.02%  [kernel]                 [k] kallsyms_expand_symbol.constprop.1
   6.27%  [kernel]                 [k] format_decode
   3.79%  [kernel]                 [k] number.isra.14
   3.50%  [kernel]                 [k] memcpy_erms
   2.33%  perf                     [.] 0x000000000008c4d6
   2.04%  [kernel]                 [k] apparmor_capable
   2.04%  [kernel]                 [k] pointer.isra.22
   1.92%  [kernel]                 [k] clear_page_c_e
   1.90%  [kernel]                 [k] string.isra.4
   1.75%  perf                     [.] 0x000000000008e314
   1.60%  libc-2.23.so             [.] getdelim
   1.60%  perf                     [.] 0x0000000000082067
   1.46%  [kernel]                 [k] strnlen
   1.46%  perf                     [.] 0x000000000008e326

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

另外,采样数需要我们特别注意。如果采样数过少(比如只有十几个),那下面的排序和 百分比就没什么实际参考价值了。

再往下看是一个表格式样的数据,每一行包含四列,分别是:

  • 第一列 Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示。

  • 第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。

  • 第三列 Object ,是动态共享对象的类型。比如 [.] 表示用户空间的可执行程序、或者动态链接库,而 [k] 则表示内核空间。

  • 最后一列 Symbol 是符号名,也就是函数名。当函数名未知时,用十六进制的地址来表示。

第二种

就是 perf record 和 perf report。perf top 虽然实时展示了系统的性能信息,但它的缺点是并不保存数据,也就无法用于离线或者后续的分析。而 perf record 则提供了保存数据的功能,保存后的数据,需要你用 perf report 解析展示。

sudo perf record -a #按 Ctrl+C 终止采样

sudo perf report #展示类似于 perf top 的报告

sudo perf top -g -p 21515 # -g 开启调用关系分析,-p 指定 php-fpm 的进程号 21515

在实际使用中,我们还经常为 perf top 和 perf record 加上 -g 参数,开启调用关系的采样,方便我们根据调用链来分析性能问题。

Nick            上次更新 2022-09-21 16:24:27

results matching ""

    No results matching ""

    results matching ""

      No results matching ""