我们描述系统性能时,不会常用系统负载、CPU上下文切换这些指标,而是用CPU利用率,它是单位时间内CPU使用情况的统计,以%号描述。那么,它是如何统计出来的,top、ps命令统计出来的%user、%system、%nice、%iowait、%steal这些指标的含义是什么,接下来带着些问题,以及具体的实例进行介绍。
一、节拍
1、内核态节拍
linux是多任务操作系统,将CPU时间划分成很小的时间片,通过时间中断和调度器来调度不同的任务,造成多任务同时运行的错觉。为了维护CPU时间,系统通过内核节拍率(内核中表示为HZ)触发时间中断,使用全局变量jiffies记录开机以来的节拍数,每发生一次+1。一般默认设置成250,具体查看方式:
zxt2000@linux-128d:~/lsm/env/ushelltest> grep 'CONFIG_HZ=' /boot/config-$(uname -r)
CONFIG_HZ=250
2、用户态节拍
除了内核节拍,还有用户空间节拍USER_HZ,其值固定为100。用户空间的信息都可以通过proc文件系统查看,而/proc/stat提供系统CPU和任务统计信息,关于CPU统计信息可以这样查看:
zxt2000@linux-128d:/> cat /proc/stat |grep cpu
cpu 958146 568 594905 779855707 289036 5 22241 0 0 0
cpu0 256794 172 122297 97240201 89098 0 4663 0 0 0
cpu1 177077 22 113796 97367885 50961 0 4503 0 0 0
cpu2 54714 1 50769 97584279 22856 2 2470 0 0 0
cpu3 34018 121 31349 97626849 22911 0 1560 0 0 0
cpu4 225662 224 105154 97312110 66998 0 3964 0 0 0
cpu5 140249 22 100397 97448266 22520 0 3096 0 0 0
cpu6 45952 4 43601 97616474 8208 0 1117 0 0 0
cpu7 23677 0 27538 97659639 5480 0 864 0 0 0
第一列表示cpu编号,其他列表示各个场景下开机以来的用户空间节拍数统计,第一行是总的指标统计,关于各列的场景可以通过man proc查看描述,这些列都是CPU的重要指标,其他性能分析工具会用,务必要熟悉:
- user (us):用户态CPU时间,不包括下面的nice时间
- nice (ni):低优先级用户态CPU时间。nice值范围-20—19,值越大,优先级越低,这里说的低优先级指1-19。
- system (sys):内核态CPU时间。
- idle (id):空闲时间,但不包括下面的iowait时间。
- iowait (wa):等待IO的时间。
- irq (hi):CPU处理硬中断的时间。
- softirq (si):CPU处理软中断的时间。
- steal (st):系统运行虚拟机时,被其他虚拟机占用CPU的时间。
- guest (guest):运行虚拟机的CPU时间。
- guest_nice (gnice):低优先级运行虚拟机的时间。
二、CPU使用率
CPU使用率:除空闲时间外的其他时间占CPU总时间的百分比,即:
你可以通过统计/proc/stat的数据来计算CPU总的和各个场景下的CPU使用率,但是这个开机以来的统计,并没有什么参考价值。一般的性能统计工具都会取3秒间隔左右的两次值,即:
如果要计算某个进程的CPU使用率, 则可以查看/proc/[pid]/stat。
上面介绍了CPU使用的计算法方法,但是实际中我们不可能真的去计算,而是利用工具来统计,不过要注意是的,性能统计工具所统计的时间间隔,多个工具的使用要保证时间间隔一致。比如,top工具的间隔是3秒,而ps是整个进程的生命周期。
三、如何查看CPU使用率
1、top:显示系统的总体内存和CPU使用情况,以及各个进程的资源使用情况。
ps:显示进程的资源使用情况。
对于top:
top - 09:15:02 up 12 days, 37 min, 11 users, load average: 0.00, 0.02, 0.05
Tasks: 221 total, 1 running, 220 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.1%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 42213M total, 41864M used, 349M free, 843M buffers
Swap: 43008M total, 0M used, 43008M free, 39541M cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 10528 864 724 S 0 0.0 0:08.44 init
2 root 20 0 0 0 0 S 0 0.0 0:00.39 kthreadd
3 root 20 0 0 0 0 S 0 0.0 0:14.84 ksoftirqd/0
第三行就是cpu统计的平均值,每一列含义在第一节介绍过。按下1就会显示所有cpu的统计值,下面就是每个进程的cpu的统计值,包括用户态和内核态综合的cpu统计值。
2、pidstat:细分进程的用户态和内核态cpu统计值,专用于分析进程。
#每1秒打印一组
root@ubuntu:/# pidstat 1 1
Linux 4.4.0-31-generic (ubuntu) 02/17/2019 _x86_64_ (4 CPU)
12:13:07 PM UID PID %usr %system %guest %CPU CPU Command
12:13:08 PM 0 7 0.00 0.90 0.00 0.90 0 rcu_sched
12:13:08 PM 0 2717 3.60 5.41 0.00 9.01 2 Xorg
....
Average: UID PID %usr %system %guest %CPU CPU Command
Average: 0 7 0.00 0.90 0.00 0.90 - rcu_sched
Average: 0 2717 3.60 5.41 0.00 9.01 - Xorg
输出包括两部分,上半部分为每个进程的统计值,具体包括:
- 用户态cpu使用率(%usr)
- 内核态cpu使用率(%system)
- 运行虚拟机cpu使用率(%guest)
- 总的cpu使用率(%cpu)
下半部分是多组数据的平均值。
四、CPU使用率过高的解决思路
- 确认cpu使用率过高:top命令观察第三行可以轻松的确认系统cpu使用率是否过高。
- 确认哪个进程cpu使用率过高:pidstat,观察各个进程的cpu使用率,确认过高的进程。
- 确认进程的哪个接口导致cpu使用率过高:perf,linux2.6.31版本后内置的性能分析工具,以事件采用为基础,分析内核的性能和应用程序的性能。
perf常用方法:
- perf top,类似于top,实时显示cpu时钟最多的函数,以此查找热点函数。
root@ubuntu:/# perf top
PerfTop: 4130 irqs/sec kernel:89.8% exact: 0.0% [4000Hz cpu-clock], (all, 4 CPUs)
-------------------------------------------------------------------------------
18.46% perf [.] 0x00000000000a0d47
11.56% libc-2.19.so [.] 0x000000000014a6e9
11.21% [kernel] [k] kallsyms_expand_symbol.constprop.1
8.13% [kernel] [k] update_iter
5.67% [kernel] [k] _raw_spin_unlock_irqrestor
输出中,主要关注下面的表格数据,每一列的含义:
- 第一列,该符号的性能事件在采样中的比例。
- 第二列,该符号所在的动态共享对象(dynamic share object),如内核、进程名、动态库、内核模块名称。
- 第三列,共享对象的类型,[.]表示用户空间的进程、动态库;[k]表示内核。
- 第四列,符号名(函数),未知时,就16进制地址表示。