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用於後續解析展示
參考