某個應用使cpu使用率100%
--CPU使用率
Linux是一個多工的作業系統,將每個cpu的時間劃分為很短的時間片,再通過排程器輪流分配給各個任務使用,因此造成多工同時執行的錯覺
為了維護cpu時間,linux通過事先定義的節拍率(核心中表示為HZ),觸發時間中斷,並使用全域性變數jiffies記錄了開機以來的節拍數
[[email protected] ~]# grep 'CONFIG_HZ=' /boot/config-$(uname -r) #預設值
CONFIG_HZ=1000
Linux通過/proc虛擬檔案系統,向用戶空間提供了系統內部狀態的資訊,而/proc/stat就提供了系統的cpu和任務統計資訊。只關注
[[email protected] ~]# 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),當系統執行在虛擬機器中的時候,被其他虛擬機器佔用的
--guest(guest),通過虛擬化執行其他作業系統時,也就是虛擬機器的cpu時間
--guest_nice(gnice),代表以低優先順序執行虛擬機器的實際
事實上,為了計算cpu使用率,效能工具一般都會取間隔一段時間(比如3秒)的兩次值,作差後,再計算出這段時間內的平均cpu使用率。
要檢視cpu使用率,就必須先讀取/proc/stat 和/proc/[pid]/stat這兩個檔案,然後再安裝上面的公式計算出來?
當然不是,各種各樣的效能分析工具已經計算好了,不過要注意的是,效能分析工具給出的是間隔一段時間的平均cpu使用率,所以要注意間隔時間的設定,特別是多個工具對比分析時,一定要保證相同的時間間隔。
--怎麼檢視cpu使用率
使用top和ps工具
--top顯示了系統總體的cpu和記憶體使用情況,以及各個程序的資源使用情況
--ps則是顯示了每個程序的資源使用情況
#預設每隔3秒重新整理一次
[[email protected] ~]# 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組資料的平均值
[[email protected] ~]# 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以後內建的效能分析工具,它以效能事件取樣為基礎,不僅可以分析系統的各種事件和核心效能,還可以用來分析指定應用程式的效能問題。
[[email protected] ~]# yum install perf -y
[[email protected] ~]# ps -ef|grep mysql
[[email protected] ~]# 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 是符號名,也就是函式名,當函式名未知時,用十六進位制的地址來表示
[[email protected] ~]# 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雖然實時展示了系統的效能資訊,但它的缺點是不儲存資訊,也就無法用於離線或者後續的分析。
[[email protected] ~]# perf record #ctrl+c終止
[[email protected] ~]# perf record
^C[ perf record: Woken up 11 times to write data ]
[ perf record: Captured and wrote 3.328 MB perf.data (53866 samples) ]
[[email protected] ~]# 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
--案例
利用[[email protected] ~]# perf top -p 4122 (mysql程序號),找出具體的函式
[[email protected] ~]# ps -ef|grep mysql
[[email protected] ~]# 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,應排查核心中的中斷服務程式。