背景
????????最近在做一些工具的預(yù)研工作,會(huì)涉及到對(duì)工具的壓力測(cè)試,分析工具的資源消耗等問(wèn)題,其中CPU 資源消耗是關(guān)鍵指標(biāo)之一。為了后續(xù)性能優(yōu)化做準(zhǔn)備,回顧了以前相關(guān)CPU優(yōu)化知識(shí),并做總結(jié)分享。希望能幫助到正在遇到相關(guān)問(wèn)題的同事。
CPU 使用率
????????cpu 使用率,是我們做嵌入式開(kāi)發(fā)者,經(jīng)常會(huì)遇到的一個(gè)性能指標(biāo)。但是每個(gè)人對(duì)他的理解可能有點(diǎn)不一樣。在這里按照我個(gè)人的理解,和大家簡(jiǎn)單介紹一下。
何為CPU 使用率
????????使用率:通常是指在一定時(shí)間內(nèi)實(shí)際使用的資源或服務(wù)與可使用的資源或服務(wù)之間的比率。
????????CPU 使用率:?就是指一定時(shí)間內(nèi),CPU實(shí)際被占用的比例。那么核心問(wèn)題來(lái)了, CPU 被占用之后,主要用來(lái)做什么了呢?
????????只有知道了CPU被用來(lái)做什么了,我們才有目標(biāo),有針對(duì)性的去優(yōu)化。
CPU 消耗在哪里?
????????我們知道CPU的核心功能就是執(zhí)行指令和處理數(shù)據(jù)。
????????從linux 系統(tǒng)中,代碼的分類(lèi),我們可以分為執(zhí)行用戶(hù)態(tài)代碼,執(zhí)行內(nèi)核態(tài)代碼,執(zhí)行中斷程序代碼。
? ? ? ? 另外,linux 是多任務(wù)操作系統(tǒng),它支持遠(yuǎn)大于CPU數(shù)量的任務(wù)同時(shí)運(yùn)行。當(dāng)然這些任務(wù)不是真的同時(shí)運(yùn)行,而是系統(tǒng)在很小的時(shí)間段內(nèi),將CPU 不斷分配給任務(wù),導(dǎo)致同時(shí)運(yùn)行的錯(cuò)覺(jué)。每個(gè)任務(wù)運(yùn)行前,CPU 需要知道從哪里加載,以及從哪里運(yùn)行。也就是說(shuō)操作系統(tǒng)需要需要提前設(shè)置好任務(wù)的CPU寄存器和程序計(jì)數(shù)器(PC)。這也是CPU的上下文。同理,任務(wù)的上下文切換,根據(jù)不同的場(chǎng)景,上下文切換的資源消耗也是不一樣的。
- 進(jìn)程上下文切換:包括了虛擬內(nèi)存、棧、全局變量等用戶(hù)空間的資源,還包括了內(nèi)核堆棧、寄存器等內(nèi)核空間的狀態(tài)的資源備份和恢復(fù)。
- 線程上下文切換(前后線程是同一個(gè)進(jìn)程):需要對(duì)線程的私有數(shù)據(jù)進(jìn)行保存,比如線程寄存器,線程棧等。
- 中斷上下文切換:只包括中斷服務(wù)程序的所必需的狀態(tài),包括 CPU 寄存器、內(nèi)核堆棧、硬件中斷參數(shù)等。
????????還有一種特殊的場(chǎng)景,那就是進(jìn)程占用CPU,但是卻不做任何事。那就是不可中斷狀態(tài)。
????????不可中斷狀態(tài)的進(jìn)程則是正處于內(nèi)核態(tài)關(guān)鍵流程中的進(jìn)程,并且這些流程是不可打斷的,比如最常見(jiàn)的是等待硬件設(shè)備的 I/O 響應(yīng),當(dāng)一個(gè)進(jìn)程向磁盤(pán)讀寫(xiě)數(shù)據(jù)時(shí),為了保證數(shù)據(jù)的一致性,在得到磁盤(pán)回復(fù)前,它是不能被其他進(jìn)程或者中斷打斷的,這個(gè)時(shí)候的進(jìn)程就處于不可中斷狀態(tài)。如果此時(shí)的進(jìn)程被打斷了,就容易出現(xiàn)磁盤(pán)數(shù)據(jù)與進(jìn)程數(shù)據(jù)不一致的問(wèn)題。
綜上所述, CPU 資源主要消耗在以下場(chǎng)景。
|
CPU性能分析工具
????????砍柴不誤磨刀功。分析CPU性能問(wèn)題時(shí),可以利用一些工具,大大提高我們的效率。本節(jié)介紹幾個(gè)好用的命令,其中可能有大家平時(shí)用到過(guò),但是對(duì)于其參數(shù)也許并沒(méi)有深入了解。
top
? ? ? ? top命令是我們?cè)诜治鲂阅軉?wèn)題時(shí),常用到的一個(gè)工具。執(zhí)行top -d 1?,-d 參數(shù)表示更新頻率。默認(rèn)3s。
yihua@ubuntu:~$ top -d 1
top - 23:36:05 up 22:14, ?4 users, ?load average: 0.48, 0.10, 0.03
Tasks: 330 total, ??1 running, 253 sleeping, ??0 stopped, ??0 zombie
%Cpu(s): ?9.9 us, 66.5 sy, ?0.0 ni, 23.6 id, ?0.0 wa, ?0.0 hi, ?0.0 si, ?0.0 st
KiB Mem : ?4013240 total, ?1004708 free, ?1293040 used, ?1715492 buff/cache
KiB Swap: ?2097148 total, ?2097148 free, ???????0 used. ?2398648 avail Mem
?Unknown command - try 'h' for help
???PID USER ?????PR ?NI ???VIRT ???RES ???SHR S ?%CPU %MEM ????TIME+ COMMAND
?10612 yihua ????20 ??0 ?120024 ??7940 ??6636 S 305.0 ?0.2 ??0:21.79 sysbench
?10623 yihua ????20 ??0 ??44380 ??4132 ??3328 R ??1.0 ?0.1 ??0:00.03 top
?????1 root ?????20 ??0 ?225544 ??9332 ??6636 S ??0.0 ?0.2 ??0:03.29 systemd
?????2 root ?????20 ??0 ??????0 ?????0 ?????0 S ??0.0 ?0.0 ??0:00.04 kthreadd
?????4 root ??????0 -20 ??????0 ?????0 ?????0 I ??0.0 ?0.0 ??0:00.00 kworker/0:0H
?????6 root ??????0 -20 ??????0 ?????0 ?????0 I ??0.0 ?0.0 ??0:00.00 mm_percpu_wq
?????7 root ?????20 ??0 ??????0 ?????0 ?????0 S ??0.0 ?0.0 ??0:00.09 ksoftirqd/0
?????8 root ?????20 ??0 ??????0 ?????0 ?????0 I ??0.0 ?0.0 ??0:00.61 rcu_sched
?????9 root ?????20 ??0 ??????0 ?????0 ?????0 I ??0.0 ?0.0 ??0:00.00 rcu_bh
????10 root ?????rt ??0 ??????0 ?????0 ?????0 S ??0.0 ?0.0 ??0:00.00 migration/0
????11 root ?????rt ??0 ??????0 ?????0 ?????0 S ??0.0 ?0.0 ??0:00.09 watchdog/0
其中第一行:top - 23:36:05 up 22:14, ?4 users, ?load average: 0.48, 0.10, 0.03
23:36:05 up 22:14, ?4 users?當(dāng)前系統(tǒng)時(shí)間,系統(tǒng)運(yùn)行時(shí)間,4個(gè)用戶(hù)登錄。
?load average: 0.48, 0.10, 0.03?系統(tǒng)1分鐘,5分鐘,15分鐘的負(fù)載。通過(guò)該參數(shù),可以判斷當(dāng)前系統(tǒng)整體資源運(yùn)行狀態(tài)。
第二行:Tasks: 330 total, ??1 running, 253 sleeping, ??0 stopped, ??0 zombie
當(dāng)前系統(tǒng)中共有330個(gè)任務(wù),1個(gè)正在運(yùn)行;253個(gè)處于休眠;0個(gè)處于停止,但是資源未回收;0個(gè)僵尸進(jìn)程。
第三行:%Cpu(s): ?9.9 us, 66.5 sy, ?0.0 ni, 23.6 id, ?0.0 wa, ?0.0 hi, ?0.0 si, ?0.0 st
表示當(dāng)前CPU的資源消耗狀態(tài)。參數(shù)詳情可參考以下。
user(通常縮寫(xiě)為 us),代表用戶(hù)態(tài) CPU 時(shí)間。注意,它不包括下面的 nice 時(shí)間,但包括了 guest 時(shí)間。即執(zhí)行用戶(hù)態(tài)代碼。
nice(通??s寫(xiě)為 ni),代表低優(yōu)先級(jí)用戶(hù)態(tài) CPU 時(shí)間,也就是進(jìn)程的 nice 值被調(diào)整為 1-19 之間時(shí)的 CPU 時(shí)間。這里注意,nice 可取值范圍是 -20 到 19,數(shù)值越大,優(yōu)先級(jí)反而越低。執(zhí)行用戶(hù)態(tài)代碼。
system(通常縮寫(xiě)為 sys),代表內(nèi)核態(tài) CPU 時(shí)間。執(zhí)行內(nèi)核態(tài)代碼。
idle(通??s寫(xiě)為 id),代表空閑時(shí)間。注意,它不包括等待 I/O 的時(shí)間(iowait)。
iowait(通常縮寫(xiě)為 wa),代表等待 I/O 的 CPU 時(shí)間。進(jìn)程不可中斷狀態(tài)持續(xù)時(shí)間。
irq(通??s寫(xiě)為 hi),代表處理硬中斷的 CPU 時(shí)間。執(zhí)行硬中斷代碼。
softirq(通常縮寫(xiě)為 si),代表處理軟中斷的 CPU 時(shí)間。執(zhí)行軟中斷代碼。
steal(通常縮寫(xiě)為 st),代表當(dāng)系統(tǒng)運(yùn)行在虛擬機(jī)中的時(shí)候,被其他虛擬機(jī)占用的 CPU 時(shí)間。
可知當(dāng)前CPU資源主要消耗在內(nèi)核態(tài)。
通過(guò)top 命令,我們可以知道關(guān)于CPU資源的以下信息。
|
vmstat
????????vmstat 是一個(gè)常用的系統(tǒng)性能分析工具,主要用來(lái)分析系統(tǒng)的內(nèi)存使用情況,也常用來(lái)分析 CPU 上下文切換和中斷的次數(shù)。
# 每隔5秒輸出1組數(shù)據(jù)
yihua@ubuntu:~$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
?r ?b ??swpd ??free ??buff ?cache ??si ??so ???bi ???bo ??in ??cs us sy id wa st
?1 ?0 ?????0 985808 246852 1477912 ???0 ???0 ????4 ????3 ???1 ?123 ?0 ?0 100 ?0 ?0
特別關(guān)注的四列內(nèi)容:
cs(context switch)是每秒上下文切換的次數(shù)。
in(interrupt)則是每秒中斷的次數(shù)。
r(Running or Runnable)是就緒隊(duì)列的長(zhǎng)度,也就是正在運(yùn)行和等待 CPU 的進(jìn)程數(shù)。
b(Blocked)則是處于不可中斷睡眠狀態(tài)的進(jìn)程數(shù)。
????????這個(gè)例子中的上下文切換次數(shù) cs 是 123 次,而系統(tǒng)中斷次數(shù) in 則是 1 次,而就緒隊(duì)列長(zhǎng)度 r 為1 ,不可中斷狀態(tài)進(jìn)程數(shù) b 都是 0。
通過(guò)vmstat 命令,我們可以在指定時(shí)間段內(nèi),得到以下信息。
|
pidstat
????????pidstat 是一個(gè)常用的進(jìn)程性能分析工具,用來(lái)實(shí)時(shí)查看進(jìn)程的 CPU、內(nèi)存、I/O 以及上下文切換等性能指標(biāo)。常用以下場(chǎng)景。
? ? ? ? 1. 查看所有進(jìn)程CPU資源消耗,確認(rèn)是哪一個(gè)進(jìn)程導(dǎo)致的CPU性能問(wèn)題
# 間隔5秒后輸出一組數(shù)據(jù)
yihua@ubuntu:~$ pidstat -u 5 1
Linux 4.15.0-213-generic (ubuntu) ??????10/24/2023 ?????_x86_64_ ???????(4 CPU)
12:15:29 AM ??UID ??????PID ???%usr %system ?%guest ??%wait ???%CPU ??CPU ?Command
12:15:35 AM ????0 ??????585 ???0.20 ???0.00 ???0.00 ???0.00 ???0.20 ????0 ?vmtoolsd
12:15:35 AM ????0 ??????879 ???0.20 ???0.00 ???0.00 ???0.00 ???0.20 ????1 ?snapd
12:15:35 AM ????0 ?????5480 ???0.00 ???0.20 ???0.00 ???0.00 ???0.20 ????2 ?kworker/2:1
12:15:35 AM ?1000 ????11892 ??42.83 ?100.00 ???0.00 ???0.00 ?100.00 ????1 ?sysbench
Average: ?????UID ??????PID ???%usr %system ?%guest ??%wait ???%CPU ??CPU ?Command
Average: ???????0 ??????585 ???0.20 ???0.00 ???0.00 ???0.00 ???0.20 ????- ?vmtoolsd
Average: ???????0 ??????879 ???0.20 ???0.00 ???0.00 ???0.00 ???0.20 ????- ?snapd
Average: ???????0 ?????5480 ???0.00 ???0.20 ???0.00 ???0.00 ???0.20 ????- ?kworker/2:1
Average: ????1000 ????11892 ??42.83 ?100.00 ???0.00 ???0.00 ?100.00 ????- ?sysbench
????????以上信息可得知,主要是sysbench?這個(gè)進(jìn)程占用了資源,且主要消耗在內(nèi)核態(tài)。該指令可以配合top 使用,若已明確系統(tǒng)CPU資源受限,可通過(guò)該命令確認(rèn)是哪一個(gè)進(jìn)程以及主要消耗在哪里。
? ? ? ? 2. 查看上下文切換的消耗,確認(rèn)是哪一個(gè)進(jìn)程或線程導(dǎo)致的CPU 問(wèn)題
yihua@ubuntu:~$ pidstat -wt 5 1
Linux 4.15.0-213-generic (ubuntu) 10/24/2023 _x86_64_ (4 CPU)
12:24:55 AM UID TGID TID cswch/s nvcswch/s Command
12:25:00 AM 0 7 - 0.78 0.00 ksoftirqd/0
12:25:00 AM 0 - 7 0.78 0.00 |__ksoftirqd/0
12:25:00 AM 0 8 - 6.64 0.00 rcu_sched
12:25:00 AM 0 - 8 6.64 0.00 |__rcu_sched
12:25:00 AM 0 11 - 0.20 0.00 watchdog/0
12:25:00 AM 0 - 11 0.20 0.00 |__watchdog/0
12:25:00 AM 0 14 - 0.20 0.00 watchdog/1
12:25:00 AM 0 - 14 0.20 0.00 |__watchdog/1
12:25:00 AM 0 20 - 0.20 0.00 watchdog/2
12:25:00 AM 0 - 20 0.20 0.00 |__watchdog/2
12:25:00 AM 0 22 - 0.20 0.00 ksoftirqd/2
12:25:00 AM 0 - 22 0.20 0.00 |__ksoftirqd/2
12:25:00 AM 0 26 - 0.20 0.00 watchdog/3
12:25:00 AM 0 - 26 0.20 0.00 |__watchdog/3
12:25:00 AM 0 28 - 1.17 0.00 ksoftirqd/3
12:25:00 AM 0 - 28 1.17 0.00 |__ksoftirqd/3
12:25:00 AM 0 287 - 0.20 0.00 kworker/2:1H
12:25:00 AM 0 - 287 0.20 0.00 |__kworker/2:1H
12:25:00 AM 0 306 - 0.20 0.00 kworker/3:1H
12:25:00 AM 0 - 306 0.20 0.00 |__kworker/3:1H
12:25:00 AM 0 585 - 12.11 0.00 vmtoolsd
12:25:00 AM 0 - 585 12.11 0.00 |__vmtoolsd
12:25:00 AM 0 - 586 0.98 0.00 |__HangDetector
12:25:00 AM 0 - 877 0.39 0.00 |__gmain
12:25:00 AM 0 - 891 0.39 0.00 |__gmain
12:25:00 AM 0 900 - 0.20 0.00 irqbalance
12:25:00 AM 0 - 900 0.20 0.00 |__irqbalance
12:25:00 AM 0 902 - 0.20 0.00 wpa_supplicant
12:25:00 AM 0 - 902 0.20 0.00 |__wpa_supplicant
12:25:00 AM 0 - 1037 1.17 0.00 |__containerd
12:25:00 AM 0 - 1096 0.78 0.00 |__containerd
12:25:00 AM 0 - 3497 0.78 0.20 |__containerd
12:25:00 AM 121 1258 - 0.20 0.00 gnome-shell
12:25:00 AM 121 - 1258 0.20 0.00 |__gnome-shell
12:25:00 AM 121 1773 - 0.98 0.00 gsd-color
12:25:00 AM 121 - 1773 0.98 0.00 |__gsd-color
12:25:00 AM 1000 1957 - 0.20 0.00 Xorg
12:25:00 AM 1000 - 1957 0.20 0.00 |__Xorg
12:25:00 AM 1000 2104 - 0.78 0.59 gnome-shell
12:25:00 AM 1000 - 2104 0.78 0.59 |__gnome-shell
12:25:00 AM 1000 - 2110 1.37 0.00 |__llvmpipe-0
12:25:00 AM 1000 - 2111 1.56 0.00 |__llvmpipe-1
12:25:00 AM 1000 - 2112 1.76 0.00 |__llvmpipe-2
12:25:00 AM 1000 - 2113 1.37 0.00 |__llvmpipe-3
12:25:00 AM 1000 2268 - 0.98 0.00 gsd-color
12:25:00 AM 1000 - 2268 0.98 0.00 |__gsd-color
12:25:00 AM 1000 2335 - 10.16 0.00 vmtoolsd
12:25:00 AM 1000 - 2335 10.16 0.00 |__vmtoolsd
12:25:00 AM 1000 - 2729 0.20 0.00 |__gmain
12:25:00 AM 1000 - 2727 0.20 0.00 |__gmain
12:25:00 AM 0 5480 - 1.37 0.00 kworker/2:1
12:25:00 AM 0 - 5480 1.37 0.00 |__kworker/2:1
12:25:00 AM 0 9193 - 0.98 0.00 kworker/1:0
12:25:00 AM 0 - 9193 0.98 0.00 |__kworker/1:0
12:25:00 AM 0 9224 - 1.17 0.00 kworker/3:0
12:25:00 AM 0 - 9224 1.17 0.00 |__kworker/3:0
12:25:00 AM 0 10778 - 7.62 0.00 kworker/u256:0
12:25:00 AM 0 - 10778 7.62 0.00 |__kworker/u256:0
12:25:00 AM 0 11010 - 0.98 0.00 kworker/0:4
12:25:00 AM 0 - 11010 0.98 0.00 |__kworker/0:4
12:25:00 AM 0 11946 - 1.95 0.00 kworker/u256:3
12:25:00 AM 0 - 11946 1.95 0.00 |__kworker/u256:3
12:25:00 AM 1000 - 11952 21298.44 184419.14 |__sysbench
12:25:00 AM 1000 - 11953 19585.35 192591.21 |__sysbench
12:25:00 AM 1000 - 11954 20186.52 173420.90 |__sysbench
12:25:00 AM 1000 - 11955 20158.59 193855.27 |__sysbench
12:25:00 AM 1000 - 11956 19719.34 178251.37 |__sysbench
12:25:00 AM 1000 - 11957 20934.38 162003.52 |__sysbench
12:25:00 AM 1000 - 11958 22238.48 162588.67 |__sysbench
12:25:00 AM 1000 - 11959 19943.55 181168.75 |__sysbench
12:25:00 AM 1000 - 11960 20675.00 177943.16 |__sysbench
12:25:00 AM 1000 - 11961 20960.35 183560.94 |__sysbench
12:25:00 AM 1000 11962 - 0.20 229.10 pidstat
12:25:00 AM 1000 - 11962 0.20 229.49 |__pidstat
Average: UID TGID TID cswch/s nvcswch/s Command
Average: 0 7 - 0.78 0.00 ksoftirqd/0
Average: 0 - 7 0.78 0.00 |__ksoftirqd/0
Average: 0 8 - 6.64 0.00 rcu_sched
Average: 0 - 8 6.64 0.00 |__rcu_sched
Average: 0 11 - 0.20 0.00 watchdog/0
Average: 0 - 11 0.20 0.00 |__watchdog/0
Average: 0 14 - 0.20 0.00 watchdog/1
Average: 0 - 14 0.20 0.00 |__watchdog/1
Average: 0 20 - 0.20 0.00 watchdog/2
Average: 0 - 20 0.20 0.00 |__watchdog/2
Average: 0 22 - 0.20 0.00 ksoftirqd/2
Average: 0 - 22 0.20 0.00 |__ksoftirqd/2
Average: 0 26 - 0.20 0.00 watchdog/3
Average: 0 - 26 0.20 0.00 |__watchdog/3
Average: 0 28 - 1.17 0.00 ksoftirqd/3
Average: 0 - 28 1.17 0.00 |__ksoftirqd/3
Average: 0 287 - 0.20 0.00 kworker/2:1H
Average: 0 - 287 0.20 0.00 |__kworker/2:1H
Average: 0 306 - 0.20 0.00 kworker/3:1H
Average: 0 - 306 0.20 0.00 |__kworker/3:1H
Average: 0 585 - 12.11 0.00 vmtoolsd
Average: 0 - 585 12.11 0.00 |__vmtoolsd
Average: 0 - 586 0.98 0.00 |__HangDetector
Average: 0 - 877 0.39 0.00 |__gmain
Average: 0 - 891 0.39 0.00 |__gmain
Average: 0 900 - 0.20 0.00 irqbalance
Average: 0 - 900 0.20 0.00 |__irqbalance
Average: 0 902 - 0.20 0.00 wpa_supplicant
Average: 0 - 902 0.20 0.00 |__wpa_supplicant
Average: 0 - 1037 1.17 0.00 |__containerd
Average: 0 - 1096 0.78 0.00 |__containerd
Average: 0 - 3497 0.78 0.20 |__containerd
Average: 121 1258 - 0.20 0.00 gnome-shell
Average: 121 - 1258 0.20 0.00 |__gnome-shell
Average: 121 1773 - 0.98 0.00 gsd-color
Average: 121 - 1773 0.98 0.00 |__gsd-color
Average: 1000 1957 - 0.20 0.00 Xorg
Average: 1000 - 1957 0.20 0.00 |__Xorg
Average: 1000 2104 - 0.78 0.59 gnome-shell
Average: 1000 - 2104 0.78 0.59 |__gnome-shell
Average: 1000 - 2110 1.37 0.00 |__llvmpipe-0
Average: 1000 - 2111 1.56 0.00 |__llvmpipe-1
Average: 1000 - 2112 1.76 0.00 |__llvmpipe-2
Average: 1000 - 2113 1.37 0.00 |__llvmpipe-3
Average: 1000 2268 - 0.98 0.00 gsd-color
Average: 1000 - 2268 0.98 0.00 |__gsd-color
Average: 1000 2335 - 10.16 0.00 vmtoolsd
Average: 1000 - 2335 10.16 0.00 |__vmtoolsd
Average: 1000 - 2729 0.20 0.00 |__gmain
Average: 1000 - 2727 0.20 0.00 |__gmain
Average: 0 5480 - 1.37 0.00 kworker/2:1
Average: 0 - 5480 1.37 0.00 |__kworker/2:1
Average: 0 9193 - 0.98 0.00 kworker/1:0
Average: 0 - 9193 0.98 0.00 |__kworker/1:0
Average: 0 9224 - 1.17 0.00 kworker/3:0
Average: 0 - 9224 1.17 0.00 |__kworker/3:0
Average: 0 10778 - 7.62 0.00 kworker/u256:0
Average: 0 - 10778 7.62 0.00 |__kworker/u256:0
Average: 0 11010 - 0.98 0.00 kworker/0:4
Average: 0 - 11010 0.98 0.00 |__kworker/0:4
Average: 0 11946 - 1.95 0.00 kworker/u256:3
Average: 0 - 11946 1.95 0.00 |__kworker/u256:3
Average: 1000 - 11952 21298.44 184419.14 |__sysbench
Average: 1000 - 11953 19585.35 192591.21 |__sysbench
Average: 1000 - 11954 20186.52 173420.90 |__sysbench
Average: 1000 - 11955 20158.59 193855.27 |__sysbench
Average: 1000 - 11956 19719.34 178251.37 |__sysbench
Average: 1000 - 11957 20934.38 162003.52 |__sysbench
Average: 1000 - 11958 22238.48 162588.67 |__sysbench
Average: 1000 - 11959 19943.55 181168.75 |__sysbench
Average: 1000 - 11960 20675.00 177943.16 |__sysbench
Average: 1000 - 11961 20960.35 183560.94 |__sysbench
Average: 1000 11962 - 0.20 229.10 pidstat
Average: 1000 - 11962 0.20 229.49 |__pidstat
????????由上可知,該命令可以配合vmstat?使用, 因?yàn)?span style="background-color:#eff0f1;">vmstat?僅能描述系統(tǒng)整體的上下文切換信息。而pidstat可以精確到具體的線程或進(jìn)程。
通過(guò)pidstat 命令,我們確認(rèn)以下信息。
|
dstat
????????dstat 是一個(gè)新的性能工具,它吸收了 vmstat、iostat、ifstat 等幾種工具的優(yōu)點(diǎn),可以同時(shí)觀察系統(tǒng)的 CPU、磁盤(pán) I/O、網(wǎng)絡(luò)以及內(nèi)存使用情況。?
yihua@ubuntu:~$ dstat 1 10
You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read ?writ| recv ?send| ?in ??out | int ??csw
??0 ??1 ?99 ??0 ??0| ?15k ??12k| ??0 ????0 | ??0 ????0 |1186 ???24k
??0 ??0 100 ??0 ??0| ??0 ????0 | 120B ?178B| ??0 ????0 | ?80 ??111
??0 ??0 ?0 ??100 ?0| ?30M ???0 | 120B ?178B| ??0 ????0 | ?53 ???85
??0 ??0 100 ??0 ??0| ??0 ????0 | ?60B ?118B| ??0 ????0 | ?47 ???81
??0 ??0 100 ??0 ??0| ??0 ????0 | ?60B ?118B| ??0 ????0 | ?37 ???63
??0 ??0 100 ??0 ??0| ??0 ????0 | ?60B ?118B| ??0 ????0 | ?52 ???89
??1 ??0 ?99 ??0 ??0| ??0 ????0 | 120B ?178B| ??0 ????0 | ?79 ??198
??0 ??0 100 ??0 ??0| ??0 ????0 | 210B ?236B| ??0 ????0 | ?48 ???72
??0 ??0 100 ??0 ??0| ??0 ????0 | ?60B ?118B| ??0 ????0 | ?49 ???86
??0 ??0 100 ??0 ??0| ??0 ????0 | ?60B ?118B| ??0 ????0 | ?55 ???87
????????由上可知,當(dāng)I/O wait 為100%時(shí),分析 磁盤(pán) ,網(wǎng)卡,換頁(yè),中斷等數(shù)據(jù),可以得知當(dāng)前是在讀取磁盤(pán)的數(shù)據(jù)變慢了。造成了阻塞。
通過(guò)dstat 命令,可以確認(rèn)I/O的性能瓶頸具體產(chǎn)生在哪個(gè)硬件設(shè)備 |
perf
????????perf 是 Linux 2.6.31 以后內(nèi)置的性能分析工具。它以性能事件采樣為基礎(chǔ),不僅可以分析系統(tǒng)的各種事件和內(nèi)核性能,還可以用來(lái)分析指定應(yīng)用程序的性能問(wèn)題??梢詭椭覀冞M(jìn)一步定位具體的代碼或函數(shù)。
常用的方式有兩種。
- perf top,類(lèi)似于 top,它能夠?qū)崟r(shí)顯示占用 CPU 時(shí)鐘最多的函數(shù)或者指令,因此可以用來(lái)查找熱點(diǎn)函數(shù),使用界面如下所示:
SQL
Samples: 1K of event 'cpu-clock', Event count (approx.): 120772854
Overhead ?Shared Object ????????????????Symbol
??31.51% ?perf ?????????????????????????[.] d_demangle_callback
???9.68% ?[kernel] ?????????????????????[k] _raw_spin_unlock_irqrestore
???6.76% ?perf ?????????????????????????[.] __symbols__insert
???6.15% ?[kernel] ?????????????????????[k] mpt_put_msg_frame
???5.77% ?[kernel] ?????????????????????[k] __softirqentry_text_start
???5.68% ?libelf-0.170.so ??????????????[.] gelf_getsym
???3.82% ?perf ?????????????????????????[.] rb_next
???1.26% ?perf ?????????????????????????[.] rb_insert_color
???1.07% ?libc-2.27.so ?????????????????[.] _int_malloc
???1.04% ?libc-2.27.so ?????????????????[.] calloc
???0.90% ?[kernel] ?????????????????????[k] clear_page_orig
???0.87% ?[kernel] ?????????????????????[k] e1000_xmit_frame
???0.87% ?[kernel] ?????????????????????[k] exit_to_usermode_loop
???0.79% ?[kernel] ?????????????????????[k] radix_tree_next_chunk
???0.69% ?libmozjs-52.so.0.0.0 ?????????[.] JS::UnmarkGrayGCThingRecursively
???0.68% ?libc-2.27.so ?????????????????[.] __libc_malloc
???0.63% ?libmozjs-52.so.0.0.0 ?????????[.] js::UnsafeTraceManuallyBarrieredEdge<JSObject*>
???0.63% ?perf ?????????????????????????[.] dso__load_sym
???0.62% ?perf ?????????????????????????[.] __demangle_java_sym
???0.62% ?perf ?????????????????????????[.] java_demangle_sym
???0.49% ?[kernel] ?????????????????????[k] filemap_map_pages
???0.48% ?[kernel] ?????????????????????[k] get_page_from_freelist
???0.48% ?libc-2.27.so ?????????????????[.] __strrchr_avx2
???0.46% ?libelf-0.170.so ??????????????[.] elf_fill
???0.42% ?[kernel] ?????????????????????[k] finish_task_switch
???0.41% ?[kernel] ?????????????????????[k] __do_page_fault
???0.41% ?libelf-0.170.so ??????????????[.] gelf_update_verdaux
???0.39% ?libslang.so.2.3.1 ????????????[.] SLerrno_strerror
???0.35% ?libmozjs-52.so.0.0.0 ?????????[.] js::gc::EdgeNeedsSweep<jsid>
???0.35% ?[kernel] ?????????????????????[k] arch_local_irq_enable
???0.32% ?[kernel] ?????????????????????[k] queue_work_on
???0.32% ?[kernel] ?????????????????????[k] kallsyms_expand_symbol.constprop.1
???0.28% ?libc-2.27.so ?????????????????[.] __strlen_avx2
???0.27% ?perf ?????????????????????????[.] dso__find_symbol
???0.25% ?libc-2.27.so ?????????????????[.] __memcpy_avx_unaligned_erms
???0.25% ?[kernel] ?????????????????????[k] kmem_cache_alloc
???0.23% ?libelf-0.170.so ??????????????[.] gelf_getrela
???0.21% ?perf ?????????????????????????[.] cplus_demangle
???0.21% ?[kernel] ?????????????????????[k] handle_mm_fault
???0.21% ?containerd ???????????????????[.] fmt.(*pp).doPrintf
???0.21% ?libelf-0.170.so ??????????????[.] gelf_getphdr
???0.21% ?libpthread-2.27.so ???????????[.] pthread_mutex_init
???0.21% ?perf ?????????????????????????[.] arch__sym_update
???0.21% ?perf ?????????????????????????[.] elf_read_build_id
???0.21% ?perf ?????????????????????????[.] symbols__fixup_duplicate.part.2
???0.21% ?perf ?????????????????????????[.] symbols__fixup_end
???0.20% ?perf ?????????????????????????[.] dso__loaded
???0.20% ?[kernel] ?????????????????????[k] find_inode_fast
???0.20% ?libmozjs-52.so.0.0.0 ?????????[.] std::__adjust_heap<unsigned int*, long, unsigned int, __gnu_cxx::__ops::_Iter_less_iter>
???0.19% ?libc-2.27.so ?????????????????[.] cfree@GLIBC_2.2.5
???0.16% ?perf ?????????????????????????[.] map__find_symbol
???0.16% ?libmozjs-52.so.0.0.0 ?????????[.] js::SetWindowProxy
???0.16% ?[kernel] ?????????????????????[k] _raw_spin_lock
???0.15% ?[kernel] ?????????????????????[k] update_iter
???0.15% ?libvmtools.so.0.0.0 ??????????[.] Backdoor_InOut
????????由上可知,perf 中的 d_demangle_callback 函數(shù)被調(diào)用頻率較高,我們則可以從該接口入手,進(jìn)行優(yōu)化。
????????2. perf record?和 perf report。 perf top 雖然實(shí)時(shí)展示了系統(tǒng)的性能信息,但它的缺點(diǎn)是并不保存數(shù)據(jù),也就無(wú)法用于離線或者后續(xù)的分析。而 perf record 則提供了保存數(shù)據(jù)的功能,保存后的數(shù)據(jù),需要你用 perf report 解析展示。
SQL
yihua@ubuntu:~$ sudo perf record
^C[ perf record: Woken up 53 times to write data ]
[ perf record: Captured and wrote 14.481 MB perf.data (289019 samples) ]
yihua@ubuntu:~$ ls
c++ ?ekuiper-demo ?emqtt-bench ?emqx ?mi-ota ?nanoMQ ?perf.data ?presureTest ?sysstat ?test ?toolchain ?tranning ?vdi ?vsomeip
yihua@ubuntu:~$ perf report
failed to open perf.data: Permission denied
yihua@ubuntu:~$ sudo perf report
Samples: 289K of event 'cpu-clock', Event count (approx.): 72254750000
Overhead ?Command ?????????Shared Object ??????????????Symbol
??36.13% ?sysbench ????????[kernel.kallsyms] ??????????[k] _raw_spin_unlock_irqrestore
??26.80% ?swapper ?????????[kernel.kallsyms] ??????????[k] native_safe_halt
??11.08% ?sysbench ????????[kernel.kallsyms] ??????????[k] __schedule
???5.69% ?sysbench ????????[kernel.kallsyms] ??????????[k] finish_task_switch
???5.34% ?sysbench ????????[kernel.kallsyms] ??????????[k] do_syscall_64
???3.30% ?sysbench ????????[kernel.kallsyms] ??????????[k] sys_sched_yield
???3.10% ?sysbench ????????libpthread-2.27.so ?????????[.] pthread_mutex_unlock
???2.96% ?sysbench ????????libc-2.27.so ???????????????[.] sched_yield
???1.71% ?sysbench ????????libpthread-2.27.so ?????????[.] __pthread_mutex_lock
???0.62% ?sysbench ????????[kernel.kallsyms] ??????????[k] exit_to_usermode_loop
???0.58% ?sysbench ????????sysbench ???????????????????[.] crc32
???0.43% ?sysbench ????????[kernel.kallsyms] ??????????[k] schedule
???0.24% ?swapper ?????????[kernel.kallsyms] ??????????[k] finish_task_switch
???0.23% ?swapper ?????????[kernel.kallsyms] ??????????[k] tick_nohz_idle_enter
???0.20% ?sysbench ????????libpthread-2.27.so ?????????[.] __lll_lock_wait
???0.14% ?swapper ?????????[kernel.kallsyms] ??????????[k] __softirqentry_text_start
???0.12% ?swapper ?????????[kernel.kallsyms] ??????????[k] tick_nohz_idle_exit
???0.09% ?Xorg ????????????[kernel.kallsyms] ??????????[k] exit_to_usermode_loop
???0.08% ?sysbench ????????sysbench ???????????????????[.] pthread_yield@plt
???0.07% ?sysbench ????????[kernel.kallsyms] ??????????[k] futex_wake
???0.06% ?sysbench ????????[kernel.kallsyms] ??????????[k] futex_wait
???0.06% ?sysbench ????????libpthread-2.27.so ?????????[.] pthread_yield
???0.06% ?sysbench ????????[kernel.kallsyms] ??????????[k] sys_futex
???0.06% ?sysbench ????????libpthread-2.27.so ?????????[.] sched_yield@plt
???0.05% ?sysbench ????????[kernel.kallsyms] ??????????[k] futex_wait_queue_me
???0.05% ?sysbench ????????libpthread-2.27.so ?????????[.] __lll_unlock_wake
???0.04% ?sysbench ????????[kernel.kallsyms] ??????????[k] _raw_spin_lock
???0.04% ?sysbench ????????[kernel.kallsyms] ??????????[k] mark_wake_futex
???0.04% ?swapper ?????????[kernel.kallsyms] ??????????[k] do_idle
???0.04% ?sysbench ????????[kernel.kallsyms] ??????????[k] do_futex
???0.03% ?sysbench ????????libm-2.27.so ???????????????[.] __ieee754_log_fma
???0.03% ?sysbench ????????sysbench ???????????????????[.] pthread_mutex_unlock@plt
???0.03% ?sysbench ????????sysbench ???????????????????[.] sb_histogram_update
???0.03% ?sysbench ????????[kernel.kallsyms] ??????????[k] futex_wait_setup
???0.03% ?sysbench ????????sysbench ???????????????????[.] sb_event_stop
???0.03% ?sysbench ????????[kernel.kallsyms] ??????????[k] get_futex_key_refs.isra.11
???0.02% ?Xorg ????????????libpixman-1.so.0.34.0 ??????[.] _pixman_internal_only_get_implementation
???0.02% ?sysbench ????????[kernel.kallsyms] ??????????[k] __unqueue_futex
???0.02% ?sysbench ????????[kernel.kallsyms] ??????????[k] get_futex_value_locked
???0.02% ?nautilus-deskto ?[kernel.kallsyms] ??????????[k] exit_to_usermode_loop
???0.02% ?sysbench ????????[kernel.kallsyms] ??????????[k] hash_futex
???0.02% ?sysbench ????????[kernel.kallsyms] ??????????[k] get_futex_key
???0.02% ?swapper ?????????[kernel.kallsyms] ??????????[k] __schedule
???0.02% ?sysbench ????????[kernel.kallsyms] ??????????[k] __softirqentry_text_start
???0.02% ?swapper ?????????[kernel.kallsyms] ??????????[k] rcu_idle_exit
???0.02% ?sysbench ????????[kernel.kallsyms] ??????????[k] native_queued_spin_lock_slowpath
???0.02% ?sysbench ????????[kernel.kallsyms] ??????????[k] wake_q_add
???0.01% ?sysbench ????????libc-2.27.so ???????????????[.] clock_gettime
???0.01% ?sysbench ????????[kernel.kallsyms] ??????????[k] plist_add
???0.01% ?swapper ?????????[kernel.kallsyms] ??????????[k] arch_cpu_idle
???0.01% ?sysbench ????????[vdso] ?????????????????????[.] __vdso_clock_gettime
???0.01% ?sysbench ????????[kernel.kallsyms] ??????????[k] wake_up_q
???0.01% ?swapper ?????????[kernel.kallsyms] ??????????[k] __cpuidle_text_start
???0.01% ?swapper ?????????[kernel.kallsyms] ??????????[k] _raw_spin_unlock_irqrestore
???0.01% ?swapper ?????????[kernel.kallsyms] ??????????[k] schedule_idle
由上可知sysbench 進(jìn)程中的 內(nèi)核態(tài) 的 _raw_spin_unlock_irqrestore?接口調(diào)用最頻繁。
通過(guò)perf命令,可以快速定位到熱點(diǎn)代碼,幫助我們確定優(yōu)化范圍。 |
CPU性能分析定位套路
????????我們已經(jīng)知道了哪些場(chǎng)景會(huì)使用到CPU。執(zhí)行用戶(hù)態(tài)代碼,執(zhí)行內(nèi)核態(tài)代碼,執(zhí)行中斷程序代碼,任務(wù)的上下文切換,進(jìn)程處于不可中斷狀態(tài)。定位相關(guān)場(chǎng)景的工具。top,vmstat,pidstat,dstat,perf。
根據(jù)以上知識(shí)點(diǎn),當(dāng)我們遇到CPU 性能瓶頸時(shí),有一個(gè)快速定位問(wèn)題的套路。思路如下圖:
通過(guò)top命令,分析獲取系統(tǒng)整體的CPU資源消耗。判斷集中消耗在哪里,即關(guān)注以下信息。
- 內(nèi)核態(tài)(sy)。系統(tǒng)內(nèi)核態(tài)占用比較高。有兩種情況:上下文切換頻繁,導(dǎo)致資源的消耗;進(jìn)程內(nèi)核代碼執(zhí)行頻繁,比如驅(qū)動(dòng)代碼,系統(tǒng)調(diào)用等。
- 通過(guò)vmstat 1 3?查看當(dāng)前系統(tǒng)上下文切換次數(shù)是否異常。若異常則說(shuō)明,大量的CPU資源消耗在上下文切換。
- 通過(guò)pidstat -uwt 1 10?查看當(dāng)前所有進(jìn)程占用的CPU 資源以及上下文切換頻率。確定異常進(jìn)程。
- 最終通過(guò)perf record+perf report定位熱點(diǎn)代碼塊。
- 用戶(hù)態(tài)(us+ni)。若用戶(hù)態(tài)占用比較高,說(shuō)明程序中存在大量的計(jì)算。
- 通過(guò)pidstat -u 1 10?查看所有進(jìn)程占用的CPU資源,確定異常進(jìn)程。
- 最終通過(guò)perf record+perf report定位熱點(diǎn)代碼塊。
- 通過(guò)pidstat -u 1 10?查看所有進(jìn)程占用的CPU資源,確定異常進(jìn)程。
- 硬中斷(hi)。硬中斷若占用比較高,存在兩種可能:中斷處理函數(shù)耗時(shí)較多;中斷源觸發(fā)頻繁。
- 通過(guò)vmstat 1 3?查看當(dāng)前系統(tǒng)中斷次數(shù)是否異常。若異常則說(shuō)明又由于真實(shí)的硬件中斷觸發(fā)導(dǎo)致的。
- 若中斷次數(shù)處于正常范圍,則說(shuō)明中斷處理接口可能出現(xiàn)了問(wèn)題。
- 通過(guò)cat /proc/interrupts?定位的中斷源,確認(rèn)頻率是否正?;蚍治鰧?duì)應(yīng)驅(qū)動(dòng)。
- 平均負(fù)載比較高。若負(fù)載比較高,直觀的現(xiàn)象就是,有些進(jìn)程可能運(yùn)行卡頓,比如ssh 客戶(hù)端。平均負(fù)載計(jì)算兩類(lèi)進(jìn)程:運(yùn)行狀態(tài)進(jìn)程,不可中斷狀態(tài)進(jìn)程。
- 通過(guò)vmstat 1 3?查看當(dāng)前運(yùn)行狀態(tài)和不可中斷狀態(tài)進(jìn)程數(shù)。若運(yùn)行狀態(tài)進(jìn)程數(shù)較多,則說(shuō)明當(dāng)前的確有很多進(jìn)程需要運(yùn)行,且是因?yàn)镃PU 資源性能不足。
- 針對(duì)這種情況,我們可以直接通過(guò)pidstat -u 1 5定位相關(guān)進(jìn)程。
- 若當(dāng)前不可中斷狀態(tài)進(jìn)程數(shù)較多,說(shuō)明當(dāng)前出現(xiàn)了I/O 瓶頸??赏ㄟ^(guò)dstat 1 10確認(rèn)磁盤(pán)讀寫(xiě),網(wǎng)絡(luò)收發(fā),內(nèi)存換頁(yè)等I/O瓶頸。
- 通過(guò)vmstat 1 3?查看當(dāng)前運(yùn)行狀態(tài)和不可中斷狀態(tài)進(jìn)程數(shù)。若運(yùn)行狀態(tài)進(jìn)程數(shù)較多,則說(shuō)明當(dāng)前的確有很多進(jìn)程需要運(yùn)行,且是因?yàn)镃PU 資源性能不足。
- 等待I/O比較高(wa)。與上述類(lèi)似,可通過(guò)dstat 1 10確認(rèn)磁盤(pán)讀寫(xiě),網(wǎng)絡(luò)收發(fā),內(nèi)存換頁(yè)等I/O瓶頸。
- 軟中斷(si)。可通過(guò)cat /proc/softirqs?查看是哪一類(lèi)軟中斷觸發(fā)頻繁。
????????以上的套路是我個(gè)人的理解,當(dāng)然還有一些其他場(chǎng)景沒(méi)有包含,但是應(yīng)該可以適用我們實(shí)際工作中90%的場(chǎng)景了。
常見(jiàn)的優(yōu)化措施
????????當(dāng)我們定位到CPU 性能瓶頸之后,下一步操作就是如何優(yōu)化。在這里根據(jù)分享一下我的經(jīng)驗(yàn),有好的場(chǎng)景或好的措施,也歡迎補(bǔ)充。
應(yīng)用程序優(yōu)化
若定位到性能瓶頸在用戶(hù)態(tài)代碼后,我們可以嘗試從以下幾方面入手。
- 編碼的角度。排除所有不必要的工作,只保留核心邏輯。比如減少循環(huán)的層次、減少遞歸、減少動(dòng)態(tài)內(nèi)存分配等等
- 編譯器優(yōu)化。很多編譯器都會(huì)提供編譯優(yōu)化選項(xiàng),適當(dāng)開(kāi)啟它們,在編譯階段可以獲得幫助。比如,gcc 提供了優(yōu)化選項(xiàng)-O2,開(kāi)啟之后會(huì)自動(dòng)對(duì)程序進(jìn)行優(yōu)化。
- 算法優(yōu)化。使用復(fù)雜度更低的算法,可以顯著提供運(yùn)算速度。比如在大數(shù)據(jù)量的情況下,使用O(nlogn)的排序算法,替換O(n^2)的冒泡算法等。
- 異步處理。使用異步處理,可以避免程序因?yàn)榈却硞€(gè)資源而一直阻塞,從而提升程序的并發(fā)處理能力。比如,輪詢(xún)事件改為事件通知,可以避免輪詢(xún)導(dǎo)致的CPU消耗。
- 多線程替換多進(jìn)程。這里主要就是節(jié)約線程上下文和進(jìn)程上下文切換的損耗了。
- 善用緩存,即空間換時(shí)間。經(jīng)常訪問(wèn)的數(shù)據(jù)或計(jì)算過(guò)程中的步驟,可以放在內(nèi)存中緩存起來(lái),加快內(nèi)存命中率,提高執(zhí)行速度。
內(nèi)核態(tài)程序優(yōu)化
????????若定位到性能瓶頸在內(nèi)核態(tài)之后,正常情況下,作為應(yīng)用開(kāi)發(fā)工程師,我們是無(wú)法去優(yōu)化內(nèi)核代碼的,當(dāng)然內(nèi)核代碼一般也很少有優(yōu)化空間。但并不代表我們就無(wú)計(jì)可施。可以嘗試從以下幾方面入手。
- CPU綁定。把進(jìn)程綁定到一個(gè)或者多個(gè)CPU上,可以提高CPU的緩存命中率,減少CPU調(diào)度帶來(lái)的上下文切換問(wèn)題。
- 優(yōu)先級(jí)調(diào)整:使用nice調(diào)整進(jìn)程的優(yōu)先級(jí),或修改進(jìn)程的調(diào)度策略。比如,適當(dāng)降低非核心應(yīng)用的優(yōu)先級(jí),增高核心應(yīng)用的優(yōu)先級(jí),可以確保核心應(yīng)用優(yōu)先被處理。
- 降低系統(tǒng)調(diào)用頻率:內(nèi)核態(tài)一般都是通過(guò)系統(tǒng)調(diào)用從用戶(hù)態(tài)進(jìn)入到內(nèi)核態(tài)。而系統(tǒng)調(diào)用也存在上下文的切換損耗,我們可以降低系統(tǒng)調(diào)用的頻率,從而減少損耗。比如用readv/writev替換read/write。
????????當(dāng)然以上的措施,在應(yīng)用程序優(yōu)化中,也可以使用。
硬中斷
????????若定位到性能瓶頸在硬中斷后,大概率就是環(huán)境出現(xiàn)了問(wèn)題,很少是驅(qū)動(dòng)異常。我們可以通過(guò)查看cat /proc/interrupts確定是哪類(lèi)中斷異常,再進(jìn)一步去排查。
I/O阻塞
????????若定位到性能瓶頸在I/O后,大概率就是硬件設(shè)備I/O性能不足導(dǎo)致的。我們一般可以從以下方面入手:
- 善用緩存。我們知道內(nèi)存的訪問(wèn)速度遠(yuǎn)遠(yuǎn)大于對(duì)磁盤(pán)的訪問(wèn)速度,我們可以使用緩沖區(qū),減少實(shí)際的磁盤(pán)或網(wǎng)絡(luò)I/O。比如,讀寫(xiě)磁盤(pán)操作中,我們盡量不使用O_DIRECT參數(shù),它表示繞過(guò)系統(tǒng)緩存,直接對(duì)磁盤(pán)進(jìn)行讀寫(xiě)。
- 優(yōu)化磁盤(pán)I/O。提升硬件性能,比如使用SSD;優(yōu)化文件系統(tǒng),比如使用ext4或XF5。提高成本。
- 引入提高I/O性能技術(shù)。比如引入iota和dma技術(shù)。技術(shù)難度大。
軟中斷
????????若定位到性能瓶頸在軟中斷后,大概率也是環(huán)境問(wèn)題,很少是驅(qū)動(dòng)異常。具體的原因可以通過(guò)查看cat /proc/softirqs確定是哪一類(lèi)軟中斷異常,再進(jìn)一步去排查,處理。
$ watch -d cat /proc/softirqs |
????????比如,經(jīng)過(guò)分析,發(fā)現(xiàn)上圖中NET_RX,也就是網(wǎng)絡(luò)數(shù)據(jù)包接收軟中斷的變化速率最快。而其他幾種類(lèi)型的軟中斷,是保證 Linux 調(diào)度、時(shí)鐘和臨界區(qū)保護(hù)這些正常工作所必需的,所以它們有一定的變化倒是正常的。那么就可以確認(rèn)是網(wǎng)卡接收數(shù)據(jù)出現(xiàn)了異常。
????????再深入分析,可能就可以結(jié)合tcpdump命令,進(jìn)行抓包,查看是哪一個(gè)數(shù)據(jù)包一直發(fā)送。從而定位到問(wèn)題原因。比如SYN FLOOD問(wèn)題 就會(huì)導(dǎo)致上述問(wèn)題。
????????處理方式:從交換機(jī)或硬件防火墻中封掉來(lái)源IP,這樣SYN FLOOD網(wǎng)絡(luò)幀就不會(huì)收到了。
總結(jié)
? ? ? ? 當(dāng)出現(xiàn)CPU性能問(wèn)題時(shí),我們第一時(shí)間往往是手足無(wú)措,不知從何下手。本身深深體驗(yàn)過(guò)這種感受,確實(shí)不好受。因此希望本文能夠幫助到正在經(jīng)歷這種痛苦的朋友。有好的案例或者場(chǎng)景也可以分享,討論。共勉~
?若我的內(nèi)容對(duì)您有所幫助,還請(qǐng)關(guān)注我的公眾號(hào)。不定期分享干活,剖析案例,也可以一起討論分享。
我的宗旨:
踩完您工作中的所有坑并分享給您,讓你的工作無(wú)bug,人生盡是坦途
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-744659.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-744659.html
到了這里,關(guān)于CPU性能優(yōu)化——“瑞士軍刀“的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!