1. 程式人生 > 實用技巧 >13 | 答疑(一):無法模擬出 RES 中斷的問題,怎麼辦?

13 | 答疑(一):無法模擬出 RES 中斷的問題,怎麼辦?

問題 1:效能工具版本太低,導致指標不全

這是使用 CentOS 的同學普遍碰到的問題。在文章中,我的 pidstat 輸出裡有一個 %wait 指標,代表程序等待 CPU 的時間百分比,這是 systat 11.5.5 版本才引入的新指標,舊版本沒有這一項。而 CentOS 軟體庫裡的 sysstat 版本剛好比這個低,所以沒有這項指標。
不過,你也不用擔心。前面我就強調過,工具只是查詢分析的手段,指標才是我們重點分析的物件。如果你的 pidstat 裡沒有顯示,自然還有其他手段能找到這個指標。
比如說,在講解系統原理和效能工具時,我一般會介紹一些 proc 檔案系統的知識,教你看懂 proc 檔案系統提供的各項指標。之所以這麼做,一方面,當然是為了讓你更直觀地理解系統的工作原理;另一方面,其實是想給你展示,效能工具上能看到的各項效能指標的原始資料來源。
這樣,在實際生產環境中,即使你很可能需要執行老版本的作業系統,還沒有許可權安裝新的軟體包,你也可以檢視 proc 檔案系統,獲取自己想要的指標。
但是,效能分析的學習,我還是建議你要用最新的效能工具來學。新工具有更全面的指標,讓你更容易上手分析。這個絕對的優勢,可以讓你更直觀地得到想要的資料,也不容易讓你打退堂鼓。
當然,初學時,你最好試著去理解效能工具的原理,或者熟悉了使用方法後,再回過頭重新學習原理。這樣,即使是在無法安裝新工具的環境中,你仍然可以從 proc 檔案系統或者其他地方,獲得同樣的指標,進行有效的分析。

問題 2:使用 stress 命令,無法模擬 iowait 高的場景


使用 stress 無法模擬 iowait 升高,但是卻看到了 sys 升高。這是因為案例中 的 stress -i 引數,它表示通過系統呼叫 sync() 來模擬 I/O 的問題,但這種方法實際上並不可靠。因為 sync() 的本意是重新整理記憶體緩衝區的資料到磁碟中,以確保同步。如果緩衝區內本來就沒多少資料,那讀寫到磁碟中的資料也就不多,也就沒法產生 I/O 壓力。這一點,在使用 SSD 磁碟的環境中尤為明顯,很可能你的 iowait 總是 0,卻單純因為大量的系統呼叫,導致了系統 CPU 使用率 sys 升高。這種情況,我在留言中也回覆過,推薦使用 stress-ng 來代替 stress。擔心你沒有看到留言,所以這裡我再強調一遍。
你可以執行下面的命令,來模擬 iowait 的問題。
# -i 的含義還是呼叫 sync,而—hdd 則表示讀寫臨時檔案
$ stress-ng -i 1 --hdd 1 --timeout 600


問題 3:無法模擬出 RES 中斷的問題

這個問題是說,即使運行了大量的執行緒,也無法模擬出重排程中斷 RES 升高的問題。
其實我在 CPU 上下文切換的案例中已經提到,重排程中斷是排程器用來分散任務到不同 CPU 的機制,也就是可以喚醒空閒狀態的 CPU ,來排程新任務執行,而這通常藉助處理器間中斷(Inter-Processor Interrupts,IPI)來實現。
所以,這個中斷在單核(只有一個邏輯 CPU)的機器上當然就沒有意義了,因為壓根兒就不會發生重排程的情況。
不過,正如留言所說,上下文切換的問題依然存在,所以你會看到, cs(context switch)從幾百增加到十幾萬,同時 sysbench 執行緒的自願上下文切換和非自願上下文切換也都會大幅上升,特別是非自願上下文切換,會上升到十幾萬。根據非自願上下文的含義,我們都知道,這是過多的執行緒在爭搶 CPU。
其實這個結論也可以從另一個角度獲得。比如,你可以在 pidstat 的選項中,加入 -u 和 -t 引數,輸出執行緒的 CPU 使用情況,你會看到下面的介面:
$ pidstat -u -t 1
 
14:24:03      UID      TGID       TID    %usr %system  %guest   %wait    %CPU   CPU  Command
14:24:04        0         -      2472    0.99    8.91    0.00   77.23    9.90     0  |__sysbench
14:24:04        0         -      2473    0.99    8.91    0.00   68.32    9.90     0  |__sysbench
14:24:04        0         -      2474    0.99    7.92    0.00   75.25    8.91     0  |__sysbench
14:24:04        0         -      2475    2.97    6.93    0.00   70.30    9.90     0  |__sysbench
14:24:04        0         -      2476    2.97    6.93    0.00   68.32    9.90     0  |__sysbench
...
從這個 pidstat 的輸出介面,你可以發現,每個 stress 執行緒的 %wait 高達 70%,而 CPU 使用率只有不到 10%。換句話說, stress 執行緒大部分時間都消耗在了等待 CPU 上,這也表明,確實是過多的執行緒在爭搶 CPU。
在這裡順便提一下,留言中很常見的一個錯誤。有些同學會拿 pidstat 中的 %wait 跟 top 中的 iowait% (縮寫為 wa)對比,其實這是沒有意義的,因為它們是完全不相關的兩個指標。
pidstat 中, %wait 表示程序等待 CPU 的時間百分比。
top 中 ,iowait% 則表示等待 I/O 的 CPU 時間百分比。
回憶一下我們學過的程序狀態,你應該記得,等待 CPU 的程序已經在 CPU 的就緒佇列中,處於執行狀態;而等待 I/O 的程序則處於不可中斷狀態。
另外,不同版本的 sysbench 執行引數也不是完全一樣的。比如,在案例 Ubuntu 18.04 中,執行 sysbench 的格式為:
$ sysbench --threads=10 --max-time=300 threads run而在 Ubuntu 16.04 中,執行格式則為(感謝 Haku 留言分享的執行命令):
$ sysbench --num-threads=10 --max-time=300 --test=threads run

問題 4:無法模擬出 I/O 效能瓶頸,以及 I/O 壓力過大的問題

這個問題可以看成是上一個問題的延伸,只是把 stress 命令換成了一個在容器中執行的 app 應用。
事實上,在 I/O 瓶頸案例中,除了上面這個模擬不成功的留言,還有更多留言的內容剛好相反,說的是案例 I/O 壓力過大,導致自己的機器出各種問題,甚至連繫統都沒響應了。
之所以這樣,其實還是因為每個人的機器配置不同,既包括了 CPU 和記憶體配置的不同,更是因為磁碟的巨大差異。比如,機械磁碟(HDD)、低端固態磁碟(SSD)與高階固態磁碟相比,效能差異可能達到數倍到數十倍。
其實,我自己所用的案例機器也只是低端的 SSD,比機械磁碟稍微好一些,但跟高階固態磁碟還是比不了的。所以,相同操作下,我的機器上剛好出現 I/O 瓶頸,但換成一臺使用機械磁碟的機器,可能磁碟 I/O 就被壓死了(表現為使用率長時間 100%),而換上好一些的 SSD 磁碟,可能又無法產生足夠的 I/O 壓力。
另外,由於我在案例中只查找了 /dev/xvd 和 /dev/sd 字首的磁碟,而沒有考慮到使用其他字首磁碟(比如 /dev/nvme)的同學。如果你正好用的是其他字首,你可能會碰到跟 Vicky 類似的問題,也就是 app 啟動後又很快退出,變成 exited 狀態。
在這裡,berryfl 同學提供了一個不錯的建議:可以在案例中增加一個引數指定塊裝置,這樣有需要的同學就不用自己編譯和打包案例應用了。所以,在最新的案例中,我為 app 應用增加了三個選項。
  • -d 設定要讀取的磁碟,預設字首為 /dev/sd 或者 /dev/xvd 的磁碟。
  • -s 設定每次讀取的資料量大小,單位為位元組,預設為 67108864(也就是 64MB)。
  • -c 設定每個子程序讀取的次數,預設為 20 次,也就是說,讀取 20*64MB 資料後,子程序退出。
你可以點選 Github 檢視它的原始碼,使用方法我寫在了這裡:
$ docker run --privileged --name=app -itd feisky/app:iowait /app -d /dev/sdb -s 67108864 -c 20
案例執行後,你可以執行 docker logs 檢視它的日誌。正常情況下,你可以看到下面的輸出:
$ docker logs app
Reading data from disk /dev/sdb with buffer size 67108864 and count 20

問題 5:效能工具(如 vmstat)輸出中,第一行資料跟其他行差別巨大

這個問題主要是說,在執行 vmstat 時,第一行資料跟其他行相比較,數值相差特別大。我相信不少同學都注意到了這個現象,這裡我簡單解釋一下。
首先還是要記住,我總強調的那句話,在碰到直觀上解釋不了的現象時,要第一時間去查命令手冊。
比如,執行 man vmstat 命令,你可以在手冊中發現下面這句話:
The first report produced gives averages since the last reboot. Additional reports give information on a sam‐pling period of length delay. The process and memory reports are instantaneous in either case.也就是說,第一行資料是系統啟動以來的平均值,其他行才是你在執行 vmstat 命令時,設定的間隔時間的平均值。另外,程序和記憶體的報告內容都是即時數值。
你看,這並不是什麼不得了的事故,但如果我們不清楚這一點,很可能卡住我們的思維,阻止我們進一步的分析。這裡我也不得不提一下,文件的重要作用。
授之以魚,不如授之以漁。我們專欄的學習核心,一定是教會你效能分析的原理和思路,效能工具只是我們的路徑和手段。所以,在提到各種效能工具時,我並沒有詳細解釋每個工具的各種命令列選項的作用,一方面是因為你很容易通過文件查到這些,另一方面就是不同版本、不同系統中,個別選項的含義可能並不相同。
所以,不管因為哪個因素,自己 man 一下,一定是最快速並且最準確的方式。特別是,當你發現某些工具的輸出不符合常識時,一定記住,第一時間查文件弄明白。實在讀不懂文件的話,再上網去搜,或者在專欄裡向我提問。
學習是一個“從薄到厚再變薄”的過程,我們從細節知識入手開始學習,積累到一定程度,需要整理成一個體系來記憶,這其中還要不斷地對這個體系進行細節修補。有疑問、有反思才可以達到最佳的學習效果。