--CPU使用率
Linux是一个多任务的操作系统,将每个cpu的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成多任务同时运行的错觉
为了维护cpu时间,linux通过事先定义的节拍率(内核中表示为HZ),触发时间中断,并使用全局变量jiffies记录了开机以来的节拍数
[root@rac2 ~]# grep 'CONFIG_HZ=' /boot/config-$(uname -r) #默认值
CONFIG_HZ=1000
Linux通过/proc虚拟文件系统,向用户空间提供了系统内部状态的信息,而/proc/stat就提供了系统的cpu和任务统计信息。只关注cpu的话。
[root@rac2 ~]# cat /proc/stat |grep ^cpu
cpu 754068 26 321049 32751985 349040 51226 32180 0 0
cpu0 398928 11 184461 16311267 198855 49476 17588 0 0
cpu1 355140 14 136588 16440717 150185 1750 14591 0 0
第一列是cpu的编号,如cpu0,cpu1,第一行没有编号的cpu,表示的所有cpu的累加。
其他列则表示不同场景下cpu的累加,单位是USER_HZ,10ms
解读重要指标:
--user(us),代表用户态cpu时间。不包括下面的nice时间,但包括guest时间
--nice(ni),代表低优先级用户态cpu时间,也就是进程的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使用率,性能工具一般都会取间隔一段时间(比如3秒)的两次值,作差后,再计算出这段时间内的平均cpu使用率。
要查看cpu使用率,就必须先读取/proc/stat 和/proc/[pid]/stat这两个文件,然后再安装上面的公式计算出来?
当然不是,各种各样的性能分析工具已经计算好了,不过要注意的是,性能分析工具给出的是间隔一段时间的平均cpu使用率,所以要注意间隔时间的设置,特别是多个工具对比分析时,一定要保证相同的时间间隔。
--怎么查看cpu使用率
使用top和ps工具
--top显示了系统总体的cpu和内存使用情况,以及各个进程的资源使用情况
--ps则是显示了每个进程的资源使用情况
#默认每隔3秒刷新一次
[root@rac2 ~]# top
top - 06:18:35 up 2 days, 5:03, 2 users, load average: 0.08, 0.14, 0.08
Tasks: 233 total, 1 running, 232 sleeping, 0 stopped, 0 zombie
Cpu(s): 1.2%us, 0.5%sy, 0.0%ni, 97.1%id, 0.9%wa, 0.2%hi, 0.2%si, 0.0%st
Mem: 3088656k total, 2956404k used, 132252k free, 69208k buffers
Swap: 3096568k total, 203548k used, 2893020k free, 1056600k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2659 grid -2 0 1306m 14m 12m S 1.3 0.5 37:06.99 oracle
4388 oracle -2 0 1467m 16m 14m S 1.0 0.6 38:34.12 oracle
2436 grid RT 0 1088m 111m 54m S 0.7 3.7 3:41.91 ocssd.bin
2570 root RT -5 563m 151m 63m S 0.7 5.0 30:36.42 ologgerd
2711 root 20 0 1180m 60m 18m S 0.7 2.0 13:23.94 crsd.bin
4529 oracle 20 0 1474m 122m 114m S 0.7 4.0 1:23.54 oracle
11 root 20 0 0 0 0 S 0.3 0.0 16:18.60 events/0
2021 root 20 0 1146m 43m 14m S 0.3 1.4 8:07.94 ohasd.bin
2382 root 20 0 1118m 40m 13m S 0.3 1.4 4:18.61 orarootagent.bi
2607 root 20 0 752m 25m 10m S 0.3 0.8 5:02.89 octssd.bin
2628 grid 20 0 1093m 29m 12m S 0.3 1.0 5:24.73 evmd.bin
2671 grid 20 0 1314m 24m 15m S 0.3 0.8 3:25.34 oracle
2675 grid -2 0 1321m 27m 14m S 0.3 0.9 7:28.67 oracle
4404 oracle 20 0 1479m 30m 20m S 0.3 1.0 3:21.32 oracle
1 root 20 0 19356 1184 920 S 0.0 0.0 0:01.71 init
第三行%cpu就是系统的cpu使用率
每一个进程都有一个%cpu使用率,表示进程的cpu使用率,它是用户态和内核态cpu使用率的总和,包括进程用户空间使用的cpu、通过系统调用执行的内核空间cpu、以及在就绪队列等待运行的cpu。在虚拟化环境汇总,它还包括了运行虚拟机时占用的cpu。
这里可以发现,top没有细分进程的用户态cpu和内核态cpu,可以使用pidstat
--用户态cpu使用率(%usr)
--内核态cpu使用率(%system)
--运行虚拟机cpu使用率(%guest)
--等待cpu使用率(%wait)
--以及总的cpu使用率(%CPU)
最后的average部分,还计算了5组数据的平均值
[root@rac2 ~]# pidstat 1 5
Linux 2.6.32-431.el6.x86_64 (rac2) 12/12/2018 _x86_64_ (2 CPU)
06:34:54 AM PID %usr %system %guest %CPU CPU Command
06:34:55 AM 2382 0.99 0.00 0.00 0.99 1 orarootagent.bi
06:34:55 AM 2570 0.99 0.00 0.00 0.99 0 ologgerd
06:34:55 AM 2628 0.99 0.00 0.00 0.99 1 evmd.bin
06:34:55 AM 2659 0.99 0.99 0.00 1.98 0 oracle
06:34:55 AM 4388 0.00 0.99 0.00 0.99 0 oracle
。。。
Average: PID %usr %system %guest %CPU CPU Command
Average: 11 0.00 0.60 0.00 0.60 - events/0
Average: 1434 0.20 0.00 0.00 0.20 - java
Average: 2379 0.20 0.20 0.00 0.40 - gipcd.bin
Average: 2395 0.40 0.60 0.00 1.00 - osysmond.bin
Average: 2570 0.80 0.40 0.00 1.20 - ologgerd
Average: 2607 0.20 0.00 0.00 0.20 - octssd.bin
Average: 2659 0.20 1.00 0.00 1.20 - oracle
Average: 2669 0.20 0.00 0.00 0.20 - oracle
CPU使用率过高怎么办
通过top、ps、pidstat等工具,可以找到cpu使用率较高(比如100%)的进程。接下来,你可能又想知道,占用cpu的到底是代码里的哪个函数呢?找到它,才能更高效、更针对的优化。
推荐工具perf,是linux2.6.31以后内置的性能分析工具,它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。
[root@mysqlhq ~]# yum install perf -y
[root@mysqlhq ~]# ps -ef|grep mysql
[root@mysqlhq ~]# perf top -p 4122
Samples: 746 of event 'cpu-clock', Event count (approx.): 75362059
Overhead Shared Object Symbol
43.43% [kernel] [k] find_get_pages
10.55% [kernel] [k] radix_tree_next_chunk
1.87% mysqld [.] lfind
1.75% libc-2.17.so [.] __memcpy_ssse3_back
1.67% mysqld [.] MYSQLparse
1.27% [kernel] [k] mpt_put_msg_frame
0.97% mysqld [.] my_hash_sort_utf8
0.77% [kernel] [k] finish_task_switch
0.74% mysqld [.] Protocol::net_store_data
0.74% [kernel] [k] _raw_spin_unlock_irqrestore
0.67% mysqld [.] mtr_commit
0.62% mysqld [.] alloc_root
0.62% mysqld [.] close_thread_table
0.61% [kernel] [k] system_call_after_swapgs
0.60% mysqld [.] Protocol::store_string_aux
0.59% mysqld [.] page_cur_search_with_match
0.55% mysqld [.] buf_page_get_gen
0.48% [kernel] [k] fget_light
0.46% mysqld [.] my_strcasecmp_utf8
0.45% [kernel] [k] xlog_space_left
0.44% mysqld [.] btr_cur_search_to_nth_level
0.43% mysqld [.] show_status_array
0.42% mysqld [.] sync_array_print_long_waits
0.42% [kernel] [k] kmem_cache_alloc
0.40% libc-2.17.so [.] __memcmp_sse4_1
0.40% mysqld [.] THD::enter_stage
0.37% mysqld [.] Item_cond::fix_fields
0.35% [kernel] [k] do_sys_poll
0.34% libc-2.17.so [.] malloc
0.34% mysqld [.] btr_search_guess_on_hash
第一行包含3个数据,分别是采样数据Samples,事件类型event和事件总数 Event count,比如这个例子中,perf总共采集了476个cpu时钟事件,而总事件数是75362059
--Overhead,是该符号的性能事件所在所有采样中的比例,用百分比来表示
--Shared,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
--Object,是动态共享对象的类型,比如[.]表示用户空间的可执行程序、或者动态链接库,而[k]则表示内核空间
--Symbol 是符号名,也就是函数名,当函数名未知时,用十六进制的地址来表示
[root@mysqlhq ~]# perf top
Samples: 1K of event 'cpu-clock', Event count (approx.): 189946503
Overhead Shared Object Symbol
9.06% [kernel] [k] find_get_pages
3.46% [kernel] [k] __do_softirq
3.27% [kernel] [k] _raw_spin_unlock_irqrestore
2.83% [kernel] [k] finish_task_switch
2.83% [kernel] [k] radix_tree_next_chunk
1.74% perf [.] __symbols__insert
1.64% [kernel] [k] clear_page
1.49% [kernel] [k] kallsyms_expand_symbol.constprop.1
1.16% libc-2.17.so [.] __memcpy_ssse3_back
1.16% libslang.so.2.2.4 [.] SLsmg_write_
第二种常见用法,就是perf recodr和perf report,perf top虽然实时展示了系统的性能信息,但它的缺点是不保存信息,也就无法用于离线或者后续的分析。
[root@mysqlhq ~]# perf record #ctrl+c终止
[root@mysqlhq ~]# perf record
^C[ perf record: Woken up 11 times to write data ]
[ perf record: Captured and wrote 3.328 MB perf.data (53866 samples) ]
[root@mysqlhq ~]# perf report --sort comm,dso,symbol | head -100
no symbols found in /usr/bin/cut, maybe install a debug package?
no symbols found in /usr/sbin/rngd, maybe install a debug package?
Failed to open /tmp/perf-2276.map, continuing without symbols
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 53K of event 'cpu-clock'
# Event count (approx.): 13466500000
#
# Overhead Command Shared Object Symbol
# ........ ............. ............................. ..............................................
#
98.21% swapper [kernel.kallsyms] [k] native_safe_halt
0.25% mysqld [kernel.kallsyms] [k] find_get_pages
0.06% mysqld [kernel.kallsyms] [k] radix_tree_next_chunk
0.05% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore
0.04% swapper [kernel.kallsyms] [k] __do_softirq
0.02% mysql libc-2.17.so [.] __strncmp_sse42
0.02% swapper [kernel.kallsyms] [k] tick_nohz_idle_exit
0.02% swapper [kernel.kallsyms] [k] rcu_process_callbacks
0.02% swapper [kernel.kallsyms] [k] run_timer_softirq
0.02% sh [kernel.kallsyms] [k] __do_page_fault
0.02% rcu_sched [kernel.kallsyms] [k] finish_task_switch
--案例
利用[root@mysqlhq ~]# perf top -p 4122 (mysql进程号),找出具体的函数
[root@mysqlhq ~]# ps -ef|grep mysql
[root@mysqlhq ~]# perf top -p 4122
Samples: 746 of event 'cpu-clock', Event count (approx.): 75362059
Overhead Shared Object Symbol
43.43% [kernel] [k] find_get_pages
10.55% [kernel] [k] radix_tree_next_chunk
1.87% mysqld [.] lfind
1.75% libc-2.17.so [.] __memcpy_ssse3_back
1.67% mysqld [.] MYSQLparse
1.27% [kernel] [k] mpt_put_msg_frame
0.97% mysqld [.] my_hash_sort_utf8
0.77% [kernel] [k] finish_task_switch
0.74% mysqld [.] Protocol::net_store_data
0.74% [kernel] [k] _raw_spin_unlock_irqrestore
0.67% mysqld [.] mtr_commit
0.62% mysqld [.] alloc_root
0.62% mysqld [.] close_thread_table
0.61% [kernel] [k] system_call_after_swapgs
0.60% mysqld [.] Protocol::store_string_aux
0.59% mysqld [.] page_cur_search_with_match
0.55% mysqld [.] buf_page_get_gen
0.48% [kernel] [k] fget_light
0.46% mysqld [.] my_strcasecmp_utf8
0.45% [kernel] [k] xlog_space_left
0.44% mysqld [.] btr_cur_search_to_nth_level
0.43% mysqld [.] show_status_array
0.42% mysqld [.] sync_array_print_long_waits
0.42% [kernel] [k] kmem_cache_alloc
0.40% libc-2.17.so [.] __memcmp_sse4_1
0.40% mysqld [.] THD::enter_stage
0.37% mysqld [.] Item_cond::fix_fields
0.35% [kernel] [k] do_sys_poll
0.34% libc-2.17.so [.] malloc
0.34% mysqld [.] btr_search_guess_on_hash
--小结
CPU使用率是最直观和最常用的系统性能指标,更是我们在排查性能问题时,通常会关注的第一个指标,所以我们要熟悉它的含义,弄清楚几种不同的cpu使用率。
--用户(%user),nice(%nice),系统(%system),等待io(%iowait),中断(%irq),软中断(%softirq)
比如说:
--用户cpu和nice cpu高,说明用户态进程占用了较多的cpu,所以应该这重排查进程的性能问题
--系统cpu高,说明内核态占用了较多的cpu,所以应该着重排查内核线程或者系统调用的问题
--io等待cpu高,说明等待io的时间比较长,应该重点排查系统存储是不是出现了问题
--软中断和硬中断高,说明软、硬中断的处理程序占用了较多的cpu,应排查内核中的中断服务程序。