CPU 使用率

最后由 griffinqiu 修改于 03月06日 05:35

#工具

$ apt install docker.io sysstat apache2-utils
$ apt install linux-tools-common linux-tools-generic linux-tools-`uname -r`
  • top 显示了系统总体的 CPU 和内存使用情况,以及各个进程的资源使用情况。
    • top 默认显示的是所有 CPU 的平均值,这个时候你只需要按下数字 1 ,就可以切换到每个 CPU 的使用率了。
    • top 的 cpu 使用率不区分用户态和系统
  • pidstat 来分析各种状态的 CPU 使用率
  • perf top 分析 CPU 性能问题
  • perf record
  • ps 则只显示了每个进程的资源使用情况。

#概率

CPU 使用率,就是除了空闲时间外的其他时间占总 CPU 时间的百分比

CPU 使用率 = 1 - 空闲时间/总 CPU 时间 CPU 使用率 = 1 - (空闲时间 1 - 空闲时间 2)/(总 CPU 时间 1 - 总 cpu 时间 2)

  • user(通常缩写为 us),代表用户态 CPU 时间。注意,它不包括下面的 nice 时间,但包括了 guest 时间。
  • nice(通常缩写为 ni),代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。这里注意,nice 可取值范围是 -20 到 19,数值越大,优先级反而越低。
  • system(通常缩写为 sys),代表内核态 CPU 时间。
  • idle(通常缩写为 id),代表空闲时间。注意,它不包括等待 I/O 的时间(iowait)。
  • iowait(通常缩写为 wa),代表等待 I/O 的 CPU 时间。
  • irq(通常缩写为 hi),代表处理硬中断的 CPU 时间。
  • softirq(通常缩写为 si),代表处理软中断的 CPU 时间。
  • steal(通常缩写为 st),代表当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间。
  • guest(通常缩写为 guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间。
  • guest_nice(通常缩写为 gnice),代表以低优先级运行虚拟机的时间。

#节拍率

# 查看节拍率
$ grep 'CONFIG_HZ=' /boot/config-$(uname -r)
CONFIG_HZ=250
# 内核还提供了一个用户空间节拍率 USER_HZ,它总是固定为 100,也就是 1/100 秒。
$ cat /proc/stat | grep ^cpu

#案例 1

机器 1

$ docker run --name nginx -p 10000:80 -itd feisky/nginx
$ docker run --name phpfpm -itd --network container:nginx feisky/php-fpm

机器 2

# 并发 10个 请求,总共100个请求
$ ab -c 10 -n 10000 http://10.0.6.181:10000/

机器 1

# 用top,查看cpu使用情况,进程cpu使用情
$ top
# 用perf top -g 开启调用关系分析,-p 指定 php-fpm 的进程号 2748
$ perf top -g -p 2748
# 发现调用关系最终到了 sqrt 和 add_function
# 拷贝出源码查找
$ docker cp phpfpm:/app .
$ grep sqrt -r app/
app/index.php:  $x += sqrt($x);
$ grep add_function -r app

#案例 2

机器 1

$ docker run --name nginx-sp -p 10000:80 -itd feisky/nginx:sp
$ docker run --name phpfpm-sp -itd --network container:nginx-sp feisky/php-fpm:sp

机器 2

$ ab -c 5 -t 600  http://10.0.6.181:10000/

机器 1

# 1. 用top发现cpu使用率80%, 但是fpm等进程的cpu加起来并不高
$ top
# 2. 用pidstat 查看也没发现特别的地方
$ pidstat 1
# 3. 回到top中发现fpm的状态多出在sleep, 并且有一些stree进程
# 4. 用pidstat 查看stree进程, 却查询不到
$ pidstat -p 342
# 5. 用ps进程查找stree这个进程也找不到
# 6. 用pstree发现stree的父进程是fpm
$ pstree
# 7. 下载源码并搜索stree, 发现是代码中调用的stree出现初始化失败, 导致用户CPU使用率升高
$ docker cp  phpfpm-sp:/app .
$ grep stress -r ./app
# 8. 用perf 来查看这种情况, 运行record等15秒钟ctrl-c
$ perf record -g
# 9. 查看报告, 发现的缺是stress最高, 调用了random相关的函数
$ perf report
$ wget https://raw.githubusercontent.com/brendangregg/perf-tools/master/execsnoop
$ chmod +x execsnoop
$ ./execsnoop

#通常无法解释的 CPU 占用率高的原因有下面两点

  1. 应用里直接调用了其他二进制程序, 这些程序通常运行时间比较短, 用过 top 等工具不容易发现
  2. 应用本身在不停的崩溃重启, 而启动过程的资源初始化, 很可能占用相当多的 CPU

https://time.geekbang.org/column/article/70476 https://time.geekbang.org/column/article/70822