前面兩個案例講的都是上下文切換導致的 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上非常強大的硬碟檔案大小分析軟體。全盤分析所有資料夾的大小,並用餅圖和列表的方式顯示。介面華麗,功能實用。在目...