--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,應排查內核中的中斷服務程序。