文章目录
基础概念
节拍器HZ
- 节拍器HZ定义每秒钟触发时间中断的次数
- 节拍器HZ为内核的可配选项,可以设置为 100、250、1000等。不同的系统可能设置不同数值
- 可以通过查询/boot/config内核选项来查看它的配置值,如命令 grep ‘CONFIG_HZ=’ /boot/config-$(uname -r)查看系统定义的节拍器
Jiffies
Jiffies是一个全局变量记录了开机以来的节拍数。每发生一次时间中断,Jiffies 的值就加 1。
USER_HZ
- 内核给用户空间定义的节拍器(节拍率 HZ 是内核选项,所以用户空间程序并不能直接访问)
- 固定为100,这样用户空间并不需要关心内核中 HZ 被设置成了多少,因为它看到的总是固定值 USER_HZ
/proc/stat
- 可以通过/proc/stat文件查看系统的 CPU 和任务统计信息
# 只保留各个CPU的数据
$ cat /proc/stat | grep ^cpu
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 编号,如 cpu0、cpu1 ,而第一行没有编号的 cpu ,表示的是所有 CPU 的累加。其他列则表示不同场景下 CPU 的累加节拍数,它的单位是 USER_HZ,也就是 10 ms(1/100 秒),所以这其实就是不同场景下的 CPU 时间
- 每一列指标的含义
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),代表以低优先级运行虚拟机的时间。
CPU 使用率
除了空闲时间外的其他时间占总 CPU 时间的百分比
查看cpu使用率的工具
常用工具
可以定位到具体进程,但无法定位到程序内部的函数调用
1. top
2. ps
3. pidstat
perf
perf top 实时展示
类似于 top,它能够实时显示占用 CPU 时钟最多的函数或者指令,因此可以用来查找热点函数
$ 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)和事件总数量
再往下看是一个表格式样的数据,每一行包含四列,分别是:
第一列 Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示。
第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
第三列 Object ,是动态共享对象的类型。比如 [.] 表示用户空间的可执行程序、或者动态链接库,而 [k] 则表示内核空间。最后一列 Symbol 是符号名,也就是函数名。当函数名未知时,用十六进制的地址来表示。
perf record 采样后保存到文件 和 perf report 解析展示
如下:
$ 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的报告
-g 参数,开启调用关系的采样,方便我们根据调用链来分析性能问题
案例
- 搭建基础环境
$ docker run --name nginx -p 10000:80 -itd feisky/nginx
$ docker run --name phpfpm -itd --network container:nginx feisky/php-fpm
- ab命令请求
$ ab -c 10 -n 10000 http://127.0.0.1:10000/
- perf命令分析(另开终端)
# -g开启调用关系分析,-p指定php-fpm的进程号21515
$ perf top -g -p 21515
按方向键切换到 php-fpm,再按下回车键展开 php-fpm 的调用关系,你会发现,调用关系最终到了 sqrt 和 add_function,如下图所示:
- 将源码从docker中复制出来分析优化即可
$ docker cp phpfpm:/app . # 从容器phpfpm中将PHP源码拷贝出来
$ grep sqrt -r app/ # 找到了sqrt调用
app/index.php: $x += sqrt($x);
$ grep add_function -r app/ # 没找到add_function调用,这其实是PHP内置函数
总结
- 用户 CPU 和 Nice CPU 高,说明用户态进程占用了较多的 CPU,所以应该着重排查进程的性能问题。
- 系统 CPU 高,说明内核态占用了较多的 CPU,所以应该着重排查内核线程或者系统调用的性能问题。
- I/O 等待 CPU 高,说明等待 I/O 的时间比较长,所以应该着重排查系统存储是不是出现了 I/O 问题。
- 软中断和硬中断高,说明软中断或硬中断的处理程序占用了较多的CPU,所以应该着重排查内核中的中断服务程序。
Tips
- 性能分析工具给出的都是间隔一段时间的平均 CPU 使用率,所以要注意间隔时间的设置
- 因为运行环境在dokcer中,perf运行时并不能准确获取相关函数名称(显示为16进制),可以使用perf record命令 保存为文件,再将文件复制到docker中,在docker使用perf report进行分析
获取docker中运行函数名的方法具体步骤如下:
1. perf record #宿主机执行生成perf.data文件
2. docker cp perf.data phpfpm:/tmp #复制文件到运行php的docker虚拟机中
3. docker exec -i -t phpfpm bash #进入虚拟机
4. cd /tmp/ #移动到存放perf.data的目录下
5. apt-get update && apt-get install -y linux-perf linux-tools procps # 安装perf
6. perf_4.9 report #分析perf.data
运行顺利的情况下 ,可以在虚拟机中查看到具体的函数名称

本文深入讲解Linux系统下CPU性能分析,涵盖节拍器HZ、Jiffies、USER_HZ概念,/proc/stat文件解读,以及使用top、ps、pidstat、perf等工具分析CPU使用率,特别介绍了perf工具的高级用法,如perftop实时展示和perfrecord采样分析。



486

被折叠的 条评论
为什么被折叠?



