cpu使用率
linux通过proc这个虚拟文件系统,提供系统内部信息,/proc/stat提供的是系统cpu信息,可以使用以下命令查看:
# cat /proc/stat |grep ^cpu
cpu 241187 1658 242572 4371878 374 0 554 0 0 0
cpu0 134376 743 93967 2199565 172 0 286 0 0 0
cpu1 106810 914 148605 2172313 202 0 267 0 0 0第一列表示cpu编号,没有编号的cpu表示所有cpu,其他列表示不同场景下cpu累加节拍数,它的单位是USER_HZ,也就是10ms(1/100s),每列具体含义,可以man proc
cpu相关指标
- user: us, 代表用户态cpu时间,它不包括nice时间,但包括guest时间
- nice: ni,代表低优先级用户态时间,就是进程nice值调整为1-19之间的cpu时间,nice值取值范围是-20~19,数值越大,优先级越低
- system:sys,代表内核态cpu时间
- idle:id,代表空闲时间,他不包括等待io时间(iowait)
- iowait:wa,代表等待io的cpu时间
- irq:hi,代表处理硬中断cpu时间
- softirq:si,代表软中断cpu时间
- steal:st,当系统运行在虚拟机中时,被其他虚拟机占用的cpu时间
- guest:guest,代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的cpu时间
- guest_nice:gnice,代表低优先级运行虚拟机时间
cpu使用率=1-空闲时间/总cpu时间,一般计算cpu使用率,会取间隔一段时间的两次值,做差后,在计算出这段时间内平均cpu使用率,性能工具给出的都是间隔一段时间内的平均cpu使用率,所以要注意间隔时间设置
- 查看cpu使用率工具
- top工具
- top工具默认显示的是所有cpu使用率平均值,要看单个cpu,可以按1,依次查看每个cpu使用率
- pidstat工具
pidstat 1 5
0:47:46 PM UID PID %usr %system %guest %wait %CPU CPU Command
10:47:47 PM 0 459 0.00 0.98 0.00 0.00 0.98 1 xfsaild/sda4
10:47:47 PM 0 28777 0.98 1.96 0.00 0.00 2.94 0 pidstat
%usr:用户态cpu使用率
%system:内核态cpu使用率
%guest:运行虚拟机cpu使用率
%wait:等待cpu使用率
%CPU:总的cpu使用率cpu使用率过高分析
调试工具gdb,gdb调试程序过程会中断程序运行,故此,一般不允许在线上环境运行,通常是找出问题函数之后,线下借助gdb进一步分析函数内部问题
生产环境调试工具建议使用perf,第一种常见用法是 perf top,它能实时显示占用cpu时钟最多的函数或者指令,可以用来查找热点函数,使用如下:
perf top
Samples: 642 of event 'cpu-clock', Event count (approx.): 90431059
Overhead Shared Object Symbol
18.63% [kernel] [k] _raw_spin_unlock_irqrestore
5.58% perf [.] __symbols__insert
5.00% [kernel] [k] mpt_put_msg_frame
3.66% [kernel] [k] vmw_cmdbuf_header_submit
2.65% [kernel] [k] finish_task_switch
2.42% perf [.] rb_next
1.85% [kernel] [k] kallsyms_expand_symbol.constprop.1
1.74% perf [.] map__process_kallsym_symbol
1.73% [kernel] [k] __softirqentry_text_start
Samples: 采样数
event:事件类型
Event count:事件总数量
Overhead:该符号的性能事件在所有采样中占的比例,用百分比显示
Shared :该函数或指令所在的动态共享对象,如内核,进程名,动态连接库名,内核模块名等
Object:动态共享对象的类型,[.]表示用户空间可执行程序或者动态链接库,[k]表示内核空间
Symbol:符号名,就是函数名,若函数名未知,则使用16禁止的地址来表示第二种常见用法
- perf record:展示系统性能信息,并提供保存功能
- perf report:解析展示perf record保存的数据
案例分析
环境说明:以nginx+php的web服务为例,需要安装perf,systat,docker,ab工具,web实例使用两个docker实例实现,一个提供web服务器,一个作为web服务器的客户端,使用ab工具,给web服务增加压力请求,开启两个终端,具体操作如下:
# docker run -it -d --name nginx -p 10000:80 feisky/nginx
# docker run -it -d --name php --network container:nginx feisky/php-fpm
# curl http://10.0.11.12:10000 访问宿主机地址的10000端口,显示It works!表示容器正常启动成功
开启ab测试:
# ab -c10 -n100 http://10.0.11.12:10000/
Requests per second: 20.51 [#/sec] (mean)
Time per request: 487.579 [ms] (mean)
Time per request: 48.758 [ms] (mean, across all concurrent requests)
Transfer rate: 3.44 [Kbytes/sec] received
从结果可以看出,nginx每秒平均请求数只有20.51,这有点差,到底哪里出了问题,我们继续追查,
一个终端上运行:
# ab -c10 -n10000 http://10.0.11.12:10000/
另一个终端运行:
top
按1,结果如下:
top - 09:50:23 up 8:00, 5 users, load average: 4.31, 1.51, 0.54
Tasks: 204 total, 7 running, 105 sleeping, 0 stopped, 0 zombie
%Cpu0 : 98.3 us, 1.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st
%Cpu1 : 97.3 us, 2.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st
KiB Mem : 2017512 total, 288396 free, 534180 used, 1194936 buff/cache
KiB Swap: 2047996 total, 2047472 free, 524 used. 1293320 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
30877 daemon 20 0 336696 16548 8868 R 39.7 0.8 0:08.92 php-fpm
30879 daemon 20 0 336696 16484 8804 R 39.7 0.8 0:09.23 php-fpm
30876 daemon 20 0 336696 16548 8868 R 39.4 0.8 0:09.21 php-fpm
30880 daemon 20 0 336696 16484 8804 R 39.4 0.8 0:08.88 php-fpm
30878 daemon 20 0 336696 16484 8804 R 38.7 0.8 0:09.06 php-fpm
30225 root 20 0 109104 6168 4388 S 0.7 0.3 0:00.61 containerd-shim
1407 root 20 0 1055344 43452 23408 S 0.3 2.2 0:43.45 containerd
1408 Debian-+ 20 0 64376 11564 7020 S 0.3 0.6 0:20.01 snmpd
29885 root 20 0 1277672 100664 47664 S 0.3 5.0 0:20.95 dockerd
30298 systemd+ 20 0 33172 4276 2972 S 0.3 0.2 0:00.15 nginx
30299 systemd+ 20 0 33136 3748 2392 S 0.3 0.2 0:00.06 nginx可以看出,php-fpm进程使用率加起来将近200%,并且每个cpu的us达到98.3%,可以看出,正式由于php进程导致cpu使用率飙升
下面使用perf工具进一步分析:
# perf top -g -p 30880 30880是php-fpm进程号
按方向键切换到php-fpm,在按下回车键展开php-fpm调用关系,最终发现sqrt和add_function函数
Samples: 205K of event 'cpu-clock', Event count (approx.): 3490439906
Children Self Shared Object Symbol
- 99.58% 0.00% php-fpm [.] zend_execute
- 96.77% 4.19% php-fpm [.] execute_ex
- 54.13% execute_ex
- 20.41% 0x8c4a7c
5.20% sqrt
- 16.71% 0x98dea3
- 4.73% 0x98dd97
4.68% add_function
下面查看源码内容:
拷贝代码到当前目录
# docker cp php:/app .
# grep sqrt -r app/
app/index.php: $x += sqrt($x);
查看代码,进行修复,然后重新运行,会发现这次nginx每秒平均请求数大幅上升了,基本算正常了
总结
- 用户cpu和nice cpu高,说明用户进程占用了较多的cpu,所以应该着重排查用户进程的性能问题
- 系统cpu高,说明内核占用较多cpu,应着重排查内核线程或者系统调用的性能问题
- io wait cpu高,说明等待io时间长,着重排查磁盘存储是否出现io问题
- 软中断和硬中断高,说明中断程序占用过多的cpu,应该着重排查内核中的中断处理程序
- 碰到cpu占用率高的问题,要借助top,pidstat工具,确认引起性能问题原因,再使用perf工具排查引起性能问题的具体函数*
可能会出现的问题
- 在centos系统上运行perf top -g -p pid,会看到16进制的东西,可能会报xxx.so错误,这一般是perf无法找到依赖的库,在分析容器应用问题经常会碰到,一般可以在容器外面把分析记录保存下来,到容器里去看结果,具体操作如下:
- 在宿主机运行perf record -g -p pid 执行一会,退出命令
- 把生成的perf.data拷贝到容器
docker cp perf.data php:/tmp
docker exec -it php /bin/bash
安装perf等工具
perf report 分析perf.data数据centos系统一般会出现上面问题,ubuntu一般不会出现,perf找不到sqr函数,只看到地址,一般是因为依赖在容器内,故而perf无法找到php符号表,解决办法就是把perf.data拷贝到容器内用perf report进行分析