我們對系統性能進行優化時,一般會使用top命令來查看系統負載和系統中各個進程的運行情況,從而找出影響系統性能的因素。如下圖所示:
top
top命令會輸出很多系統相關的信息,如:系統負載、系統中的進程數、CPU使用率和內存使用率等,這些信息對排查系統性能問題起著至關重要的作用。
本文主要介紹top命令中的iowait指標(如上圖中紅色方框所示)的含義和作用。
什么是iowait
什么是iowait?我們來看看 Linux 的解釋:
Show the percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request.
中文翻譯的意思就是:CPU 在等待磁盤 I/O 請求完成時,處于空閑狀態的時間百分比(此時正在運行著idle進程)。
可以看出,如果系統處于iowait狀態,那么必須滿足以下兩個條件:
系統中存在等待 I/O 請求完成的進程。
系統當前正處于空閑狀態,也就是說沒有可運行的進程。
iowait統計原理
既然我們知道了iowait的含義,那么接下來看看 Linux 是怎么統計iowait的比率的。
Linux 會把iowait占用的時間輸出到/proc/stat文件中,我們可以通過一下命令來獲取到iowait占用的時間:
cat/proc/stat
命令輸出如下圖所示:
stat
紅色方框中的數據就是iowait占用的時間。
我們可以每隔一段時間讀取一次/proc/stat文件,然后把兩次獲取到的iowait時間進行相減,得到的結果是這段時間內,CPU處于iowait狀態的時間。接著再將其除以總時間,得到iowait占用總時間的比率。
現在我們來看看/proc/stat文件是怎樣獲取iowait的時間的。
在內核中,每個 CPU 都有一個cpu_usage_stat結構,主要用于統計 CPU 一些信息,其定義如下:
structcpu_usage_stat{ cputime64_tuser; cputime64_tnice; cputime64_tsystem; cputime64_tsoftirq; cputime64_tirq; cputime64_tidle; cputime64_tiowait; cputime64_tsteal; cputime64_tguest; cputime64_tguest_nice; };
cpu_usage_stat結構的iowait字段記錄了 CPU 處于iowait狀態的時間。
所以要獲取系統處于iowait狀態的總時間,只需要將所有 CPU 的iowait時間相加即可,代碼如下(位于源文件fs/proc/stat.c):
staticintshow_stat(structseq_file*p,void*v) { u64iowait; ... //1.遍歷系統中的所有CPU for_each_possible_cpu(i){ ... //2.獲取CPU對應的iowait時間,并相加 iowait=cputime64_add(iowait,kstat_cpu(i).cpustat.iowait); ... } ... return0; }
show_stat()函數首先會遍歷所有 CPU,然后讀取其iowait時間,并且將它們相加。
增加iowait時間
從上面的分析可知,每個 CPU 都有一個用于統計iowait時間的計數器,那么什么時候會增加這個計數器呢?
答案是:系統時鐘中斷。
在系統時鐘中斷中,會調用account_process_tick()函數來更新 CPU 的時間,代碼如下:
voidaccount_process_tick(structtask_struct*p,intuser_tick) { cputime_tone_jiffy_scaled=cputime_to_scaled(cputime_one_jiffy); structrq*rq=this_rq(); //1.如果當前進程處于用戶態,那么增加用戶態的CPU時間 if(user_tick){ account_user_time(p,cputime_one_jiffy,one_jiffy_scaled); } //2.如果前進程處于內核態,并且不是idle進程,那么增加內核態CPU時間 elseif((p!=rq->idle)||(irq_count()!=HARDIRQ_OFFSET)){ account_system_time(p,HARDIRQ_OFFSET,cputime_one_jiffy, one_jiffy_scaled); } //3.如果當前進程是idle進程,那么調用account_idle_time()函數進行處理 else{ account_idle_time(cputime_one_jiffy); } }
我們主要關注當前進程是idle進程的情況,這是內核會調用account_idle_time()函數進行處理,其代碼如下:
voidaccount_idle_time(cputime_tcputime) { structcpu_usage_stat*cpustat=&kstat_this_cpu.cpustat; cputime64_tcputime64=cputime_to_cputime64(cputime); structrq*rq=this_rq(); //1.如果當前有進程在等待IO請求的話,那么增加iowait的時間 if(atomic_read(&rq->nr_iowait)>0){ cpustat->iowait=cputime64_add(cpustat->iowait,cputime64); } //2.否則增加idle的時間 else{ cpustat->idle=cputime64_add(cpustat->idle,cputime64); } }
account_idle_time()函數的邏輯比較簡單,主要分以下兩種情況進行處理:
如果當前有進程在等待 I/O 請求的話,那么增加iowait的時間。
如果當前沒有進程在等待 I/O 請求的話,那么增加idle的時間。
所以,從上面的分析可知,要增加iowait的時間需要滿足以下兩個條件:
當前進程是idle進程,也就是說 CPU 處于空閑狀態。
有進程在等待 I/O 請求完成。
進一步說,當 CPU 處于iowait狀態時,說明 CPU 處于空閑狀態,并且系統中有進程因為等待 I/O 請求而阻塞,也說明了 CPU 的利用率不夠充分。
這時,我們可以使用異步 I/O(如iouring)來優化程序,使得進程不會被 I/O 請求阻塞。
審核編輯:劉清
-
cpu
+關注
關注
68文章
10826瀏覽量
211162 -
LINUX內核
+關注
關注
1文章
316瀏覽量
21619 -
時鐘中斷
+關注
關注
0文章
4瀏覽量
7692
原文標題:系統性能分析之|iowait是什么?
文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論