分享效能分析小案例!超實用!

2021-10-09 01:37:16 字數 3598 閱讀 8593

前面兩個案例講的都是上下文切換導致的 cpu 使用率公升高

這一篇就來講講等待 i/o 導致的 cpu 使用率公升高的案例

當 iowait 公升高時,程序很可能因為得不到硬體的響應,而長時間處於不可中斷狀態

不可中斷也是為了保護程序資料和硬體狀態一致,並且正常情況下,不可中斷狀態在很短時間內就會結束

所以,短時的不可中斷程序,一般可以忽略

但如果系統或硬體發生了故障,程序可能會在不可中斷狀態保持很久,甚至導致系統**現大量不可中斷程序。這時,就得注意下,系統是不是出現了 i/o 等效能問題

多程序引用很容易碰到的問題

乙個程序建立了子程序後,它應該通過系統呼叫 wait() 或 waitpid() 等待子程序結束,**子程序的資源

而子程序在結束時,會向它的父程序傳送 sigchld 訊號

所以,父程序還可以註冊 sigchld 訊號的處理函式,非同步**資源

如果父程序沒有**資源,或是子程序執行太快,父程序還沒來得及處理子程序狀態,子程序就已經提前退出,那這時的子程序就會變成殭屍程序

形象比喻:父親應該一直對兒子負責, 善始善終,如果不作為或者跟不上,都會導致「問題少年」的出現

殭屍程序持續的時間都比較短,在父程序**它的資源後就會消亡,或者在父程序退出後,由 init 程序**後也會消亡

一旦父程序沒有處理子程序的終止,還一直保持執行狀態,那麼子程序就會一直處於殭屍狀態

大量的殭屍程序會用盡 pid 程序號,導致新程序不能建立

ubuntu 18.04, 2 cpu,2gb 記憶體

前置條件:已執行案例應用

狀態有 ss+、d+、r+

小s:表示這個程序是乙個會話的領導程序

+:表示前台程序組

它們是用來管理一組相互關聯的程序

程序組:比如每個子程序都是父程序所在組的成員

會話:共享同乙個控制終端的乙個或多個程序組

通過 ssh 登入伺服器,就會開啟乙個控制終端(tty),這個控制終端就對應 乙個會話

而在終端中執行的命令以及它們的子程序,就構成了乙個個的程序組

在後台執行的命令,構成後台程序組

在前台執行的命令,構成前台程序組

平均負載,過去 1min、5min、15min 的平均負載依次減少,說明平均負載正在公升高

而 1min 內的平均負載已經達到系統 cpu 個數,說明系統很可能存在效能瓶頸

115 zombie 說明殭屍程序比較多,而且在不停增加,有子程序在退出時沒被清理

使用者 cpu 和系統 cpu 都不高,但 iowait 分別是 60.5% 和 94.6%,好像有點兒不正常,導致系統的平均負載公升高

ps -e -o stat,ppid,pid,cmd | egrep 『1』或

ps -ef | grep 「defunct」

一提到 iowait 公升高,首先會想要查詢系統的 i/o 情況

dstat 1 10

當 iowait 公升高(wai)時,磁碟的讀請求(read)都會很大(m)

這說明 iowait 的公升高跟磁碟的讀請求有關,很可能就是讀磁碟導致的

不可中斷狀態代表程序在跟硬體進行互動,很可能就是讀磁碟

pidstat -d -p 12407 1 5

-d 展示 i/o 統計資料

-p 指定程序號

間隔 1 秒輸出 5 組資料

kb_rd 表示每秒讀的 kb 數, kb_wr 表示每秒寫的 kb 數,iodelay 表示 i/o 的延遲(單位是時鐘週期)

它們都是 0,那就表示此時沒有任何的讀寫,說明問題不 是 12407 程序導致的,也並不是12406 程序導致的

pidstat -d 1 10

ps aux | grep 15973

這程序已經是 z 狀態,就是殭屍程序了

殭屍程序都是已經退出的程序, 所以就沒法兒繼續分析它的系統呼叫

關於殭屍程序的處理方法,我們一會兒再說,現在還是繼續分析 iowait 的問題

系統 iowait 的問題還在繼續,但是 top、pidstat 這類工具已經不能給出更多的資訊了

此時可以通過 perf 動態跟蹤效能事件

perf record -g

15s 後 ctrl+c 終止錄製

perf report

並且從 new_sync_read 和 blkdev_direct_io 能看出,程序正在對磁碟進行直接讀,也就是繞過了系統快取,每個讀請求都會從磁碟直接讀,這就可以解釋觀察到的 iowait 公升高了

iowait 已經非常低了,只有 0.3%

說明修改原始碼已經成功修復了 iowait 高的問題

不過,仔細觀察殭屍程序的數量,會發現,殭屍程序還在不斷的增長中

殭屍程序是因為父程序沒有**子程序的資源而出現的

解決殭屍程序需要先找出父程序,然後在父程序裡解決

pstree -aps 51780

ps -e -o stat,ppid,pid,cmd | egrep 『2

』所有殭屍程序的父程序都是 51688,從而確認 51688 就是殭屍程序的父程序

有沒有呼叫 wait() 或 waitpid() 

或有沒有註冊 sigchld 訊號的處理函式

把 wait() 放到了 for 死迴圈的外面,也就是說, wait() 函式實際上並沒被呼叫到,把它挪到 for 迴圈的裡面就可以了。

殭屍程序(z 狀態)沒有了, iowait 也是 0,問題終於全部解決了

這個案例是因為磁碟 i/o 導致了 iowait 公升高

不過,iowait 高並不一定代表 i/o 有效能瓶頸

當系統中只有 i/o 型別的程序在執行時,iowait 也會很高,但實際上,磁碟的讀寫遠沒有達到效能瓶頸的程度

通過 top 檢視系統資源情況

發現平均負載逐漸公升高,iowait(wa)比較高,但使用者態和核心態 cpu 使用率並不算高

檢視是否有 cpu 使用率偏高的程序,發現有 d 狀態的程序,可能是在等待 i/o 中

過一陣子會變成 z 狀態程序,且 cpu 使用率上公升,然後會看到 zombie 程序數逐漸增加

可以得到兩個結論:殭屍程序過多,應該是父程序沒有清理已經結束的子程序的資源;iowait 的上公升導系統平均負載上公升

因為是 iowait 較高,可以通過 dstat 檢視系統的 i/o 情況,會發現每次 iowait 公升高,讀磁碟請求都會很大

通過 pidstat -d 檢視 d 狀態程序的 i/o 情況,但發現並沒有有效資訊

通過 pidstat -d 直接檢視系統的 i/o 情況,可以發現不斷有新程序在進行讀磁碟操作

通過 ps 命令檢視剛剛 d 狀態程序當前的程序狀態,發現已經變成殭屍程序

通過 pstree 找到 z 狀態程序的父程序

通過 ps 命令確認所有殭屍程序的父程序

找到父程序源**,檢查 wait() / waitpid() 的是否會成功呼叫,或是 sigchld 訊號處理函式的註冊就行了

修改完全部原始碼後,重新執行應用,通過 top 驗證是否還有 iowait 過高和出現 zombie 程序的情況

zz ↩︎

zz ↩︎

超實用Mac軟體分享

我始終認為,良好的基礎設計加上超強的擴充套件性才是乙個好系統。mac系統也有很多缺點和不足,雖然是出於設計考慮,但是實際上,對於使用的人來說,造成了很多不方便。雖然我不認為mac是最棒的作業系統,但是mac一定是乙個很有潛力的作業系統。下面推薦一些實用軟體,對於提公升使用體驗很不錯。easyfind...

超實用Mac軟體分享

我始終認為,良好的基礎設計加上超強的擴充套件性才是乙個好系統。mac系統也有很多缺點和不足,雖然是出於設計考慮,但是實際上,對於使用的人來說,造成了很多不方便。雖然我不認為mac是最棒的作業系統,但是mac一定是乙個很有潛力的作業系統。下面推薦一些實用軟體,對於提公升使用體驗很不錯。easyfind...

超實用Mac軟體分享(二)

上一次推薦了一些軟體,發給一些朋友後,大家試用了一下說有些還是不錯的。後來又有朋友陸陸續續推薦了一些其他軟體,並且我發現自己還有一些軟體也沒全寫上,所以再做個續篇吧。dasydisk mac上非常強大的硬碟檔案大小分析軟體。全盤分析所有資料夾的大小,並用餅圖和列表的方式顯示。介面華麗,功能實用。在目...