Linux性能优化-CPU使用率

Linux作为一个多任务操作系统,将每个CPU的时间划分成很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成了多个任务同时运行的错觉
为了维护CPU时间,Linux通过实现定义的节拍率(内核中表示为HZ),触发时间中断,并使用全局变量Jiffies记录了开机以来的节拍数,每发生一次时间中断,Jiffies的值就加1
节拍率HZ是内核的可配选项,可以设置为100,250,1000等,不同的系统可能设置不同数值,你可以通过查询
/boot/config 内核选项来查看他的配置值,
比如下面这个,就是每秒有1000个次的时间中断

cat /boot/config-3.10.0-514.16.1.el7.x86_64 | grep HZ
CONFIG_NO_HZ_COMMON=y
# CONFIG_HZ_PERIODIC is not set
# CONFIG_NO_HZ_IDLE is not set
CONFIG_NO_HZ_FULL=y
# CONFIG_NO_HZ_FULL_ALL is not set
CONFIG_NO_HZ=y
# CONFIG_RCU_FAST_NO_HZ is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_MACHZ_WDT=m

这个节拍率HZ是内核选项,所以用户空间程序并不能直接访问,为了方便用户空间程序,内核还提供了一个用户空间节拍率 USER_HZ,它总是固定为100,也就是1/100秒


Linux通过/proc 虚拟文件系统,向用户空间提供了系统内部状态的信息,而 /proc/stat 提供的就是系统的CPU和任务统计信息,如果只关注CPU的话,可以执行下面命令

CPU      user%           nice%   system%  idle%              iowait%  irq%    softirq%  steal%  guest_nice%
cpu     46690956        1395    2756716 1100812644      62551   933     216878  35728   0
cpu0    11685110        348     676302  275161847       2032    179     80539   19513   0
cpu1    11655846        375     624830  275424074       1597    65      6651    2351    0
cpu2    11648679        337     680955  275312231       16027   222     36922   3776    0
cpu3    11701320        334     774627  274914491       42894   465     92765   10087   0

每一列的含义如下
1.user(缩写us),表示用户态CPU时间,不包括下面的nice时间,但包括了guest时间
2.nice(缩写ni),表示低优先级用户态CPU时间,进程nice值为1-19之间的CPU时间,-20(最高)到19(最底)
3.sysem(sys),代表内核态CPU时间
4.idle(id)代表空闲时间,但不包括等待I/O的时间
5.iowait(wa),代表等待I/O的CPU时间
6.irq(hi),代表处理硬件中断的CPU时间
7.softirq(si),代表处理软中断的CPU时间
8.steal(st),代表系统运行在虚拟机中的时候,被其他虚拟机占用的CPU时间
9.guest(guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的CPU时间
10.guest_nice(gnice),代表以低优先运行虚拟机的时间

我们通常所说的CPU使用率,是除了空闲时间外的其他时间占总CPU时间的百分比,用公式来表示为

根据这个公式,我们就可以从/proc/stat中的数据,计算出CPU使用率,
这个文件中的值就是开机以来的节拍数累加值,直接算出来的,是开机以来的平均CPU使用率
为了计算CPU使用率,性能工具一般都会取间隔一段时间(如3秒)的两次值,做差之后,再计算这段时间内的平均CPU使用率,公式如下

除了/proc/stat,还有/proc/[PID]/stat 这个文件
这两个文件都会被各种系统性能分析工具读取并解析,所以这两个工具是系统指标的来源
性能分析工具给出的都是一段时间的平均CPU使用率,所以要注意间隔时间的设置,特别是用多个工具对比分析时,一定要保证他们用的是相同的间隔时间
比如top默认使用3秒时间间隔,而ps使用的是整个进程的生命周期
 

除了/proc/stat,还有/proc/[PID]/stat 这个文件
这两个文件都会被各种系统性能分析工具读取并解析,所以这两个工具是系统指标的来源
性能分析工具给出的都是一段时间的平均CPU使用率,所以要注意间隔时间的设置,特别是用多个工具对比分析时,一定要保证他们用的是相同的间隔时间
比如top默认使用3秒时间间隔,而ps使用的是整个进程的生命周期


top显示了系统总体的CPU和内存使用情况,以及各个进程的资源使用情况
ps 则只显示了每个进程的资源使用情况
top的第三行就是CPU的各个指标的使用率情况
pidstat命令显示每个进程的CPU使用率情况


GDB(The GUN Project Debugger),是一个程序调试工具,在调试程序错误方面很强大,但在调试程序的过程中会中断程序运行,在线上环境就不合适了,只适用于性能分析的后期,找到问题的大致函数后,线下再借助这个工具来进一步调试函数内部的问题
perf比较适合在线上环境做性能分析,它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定营业程序的性能问题
比如perf top,类似top,能显示占用CPU始终最多的函数或指令,因此可以用来查找热点函数

Samples: 555  of event 'cpu-clock', Event count (approx.): 112367154                                                                                                    
Overhead  Shared Object            Symbol                                                                                                                               
   8.01%  [kernel]                 [k] vsnprintf
   4.28%  libc-2.17.so             [.] __strcmp_sse42
   3.75%  [kernel]                 [k] format_decode
   3.58%  [kernel]                 [k] __memcpy
   3.58%  [kernel]                 [k] kallsyms_expand_symbol.constprop.1
   3.07%  perf                     [.] 0x00000000000c53b4
   2.85%  [kernel]                 [k] _raw_spin_unlock_irqrestore
   2.73%  perf                     [.] __dso__load_kallsyms
   2.44%  perf                     [.] rb_next
   2.38%  perf                     [.] hex2u64
   2.10%  [kernel]                 [k] finish_task_switch
   1.87%  [kernel]                 [k] module_get_kallsym
   1.87%  [kernel]                 [k] number.isra.2
   1.70%  [kernel]                 [k] strnlen
   1.70%  libc-2.17.so             [.] _IO_getdelim
   1.70%  libc-2.17.so             [.] __memcpy_sse2
   1.57%  libc-2.17.so             [.] _int_malloc
   1.56%  libc-2.17.so             [.] __strchr_sse42
   1.54%  libc-2.17.so             [.] __memcpy_ssse3_back
   1.53%  perf                     [.] 0x00000000000c53c7
   1.42%  [kernel]                 [k] tick_nohz_idle_enter
   1.36%  [kernel]                 [k] string.isra.7
   1.27%  libpthread-2.17.so       [.] pthread_rwlock_unlock
   1.19%  [kernel]                 [k] pointer.isra.19
   1.07%  perf                     [.] rb_insert_color
   1.02%  libc-2.17.so             [.] __strlen_sse2_pminub
   0.86%  [kernel]                 [k] run_timer_softirq
   0.73%  libpthread-2.17.so       [.] pthread_rwlock_rdlock
   0.73%  perf                     [.] __symbols__insert
   0.71%  libc-2.17.so             [.] __memset_sse2
   0.68%  [kernel]                 [k] strlcpy
   0.68%  libc-2.17.so             [.] _IO_feof
   0.68%  libc-2.17.so             [.] memchr
   0.68%  libpthread-2.17.so       [.] pthread_mutex_init
   0.68%  perf                     [.] rb_erase
   0.67%  libc-2.17.so             [.] _int_free
   0.62%  libelf-0.168.so          [.] gelf_getsym
   0.62%  perf                     [.] symbols__insert
   0.61%  [kernel]                 [k] __do_softirq
   0.61%  [kernel]                 [k] rcu_gp_kthread
   0.56%  [kernel]                 [k] mem_cgroup_charge_common
   0.56%  perf                     [.] dso__load_sym
   0.51%  [kernel]                 [k] __x86_indirect_thunk_rax
   0.51%  [kernel]                 [k] clear_page_c_e

输出结果中,第一行包含三个数据
分别是采样数(Samples),时间类型(event)和事件总数量(Event count)
这里的采样了555个CPU时钟事件,事件总数是112367154个,如果采样数过少(只有十几个)那么排序和百分比意义就不大了
再往下看是一个表格样式数据,每一行包含四列,分别是
1.Overhead, 是该符号的性能事件在所有采样中的比例,用百分比来表示
2.Shared,   是该函数或指令所在的动态共享对象(Dynamic Shared Object)如内核,进程名,动态链接库
  的名字,内核模块名字等
3.Object,   是动态共享对象的类型,比如[.]表示用户空间的可执行程序,或动态链接库,而[k]表示
   内核空间
4.Symbol,   是符号名,也就是函数名,当函数名未知时,用16进制的地址来表示
perf工具本身也会占用一定的CPU

perf top虽然实时展示了系统的性能信息,但他的缺点是并不保存数据,也就无法用于离线或后续分析,使用
perf record 保存数据,perf report用于后续解析展示

参考

CONFIG_HZ 和 USER_HZ

猜你喜欢

转载自blog.csdn.net/hixiaoxiaoniao/article/details/85008873