我們對系統(tǒng)性能進行優(yōu)化時,一般會使用top命令來查看系統(tǒng)負載和系統(tǒng)中各個進程的運行情況,從而找出影響系統(tǒng)性能的因素。如下圖所示:

top
top命令會輸出很多系統(tǒng)相關(guān)的信息,如:系統(tǒng)負載、系統(tǒng)中的進程數(shù)、CPU使用率和內(nèi)存使用率等,這些信息對排查系統(tǒng)性能問題起著至關(guān)重要的作用。
本文主要介紹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 請求完成時,處于空閑狀態(tài)的時間百分比(此時正在運行著idle進程)。
可以看出,如果系統(tǒng)處于iowait狀態(tài),那么必須滿足以下兩個條件:
系統(tǒng)中存在等待 I/O 請求完成的進程。
系統(tǒng)當前正處于空閑狀態(tài),也就是說沒有可運行的進程。
iowait統(tǒng)計原理
既然我們知道了iowait的含義,那么接下來看看 Linux 是怎么統(tǒng)計iowait的比率的。
Linux 會把iowait占用的時間輸出到/proc/stat文件中,我們可以通過一下命令來獲取到iowait占用的時間:
cat/proc/stat
命令輸出如下圖所示:

stat
紅色方框中的數(shù)據(jù)就是iowait占用的時間。
我們可以每隔一段時間讀取一次/proc/stat文件,然后把兩次獲取到的iowait時間進行相減,得到的結(jié)果是這段時間內(nèi),CPU處于iowait狀態(tài)的時間。接著再將其除以總時間,得到iowait占用總時間的比率。
現(xiàn)在我們來看看/proc/stat文件是怎樣獲取iowait的時間的。
在內(nèi)核中,每個 CPU 都有一個cpu_usage_stat結(jié)構(gòu),主要用于統(tǒng)計 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結(jié)構(gòu)的iowait字段記錄了 CPU 處于iowait狀態(tài)的時間。
所以要獲取系統(tǒng)處于iowait狀態(tài)的總時間,只需要將所有 CPU 的iowait時間相加即可,代碼如下(位于源文件fs/proc/stat.c):
staticintshow_stat(structseq_file*p,void*v)
{
u64iowait;
...
//1.遍歷系統(tǒng)中的所有CPU
for_each_possible_cpu(i){
...
//2.獲取CPU對應的iowait時間,并相加
iowait=cputime64_add(iowait,kstat_cpu(i).cpustat.iowait);
...
}
...
return0;
}
show_stat()函數(shù)首先會遍歷所有 CPU,然后讀取其iowait時間,并且將它們相加。
增加iowait時間
從上面的分析可知,每個 CPU 都有一個用于統(tǒng)計iowait時間的計數(shù)器,那么什么時候會增加這個計數(shù)器呢?
答案是:系統(tǒng)時鐘中斷。
在系統(tǒng)時鐘中斷中,會調(diào)用account_process_tick()函數(shù)來更新 CPU 的時間,代碼如下:
voidaccount_process_tick(structtask_struct*p,intuser_tick)
{
cputime_tone_jiffy_scaled=cputime_to_scaled(cputime_one_jiffy);
structrq*rq=this_rq();
//1.如果當前進程處于用戶態(tài),那么增加用戶態(tài)的CPU時間
if(user_tick){
account_user_time(p,cputime_one_jiffy,one_jiffy_scaled);
}
//2.如果前進程處于內(nèi)核態(tài),并且不是idle進程,那么增加內(nèi)核態(tài)CPU時間
elseif((p!=rq->idle)||(irq_count()!=HARDIRQ_OFFSET)){
account_system_time(p,HARDIRQ_OFFSET,cputime_one_jiffy,
one_jiffy_scaled);
}
//3.如果當前進程是idle進程,那么調(diào)用account_idle_time()函數(shù)進行處理
else{
account_idle_time(cputime_one_jiffy);
}
}
我們主要關(guān)注當前進程是idle進程的情況,這是內(nèi)核會調(diào)用account_idle_time()函數(shù)進行處理,其代碼如下:
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()函數(shù)的邏輯比較簡單,主要分以下兩種情況進行處理:
如果當前有進程在等待 I/O 請求的話,那么增加iowait的時間。
如果當前沒有進程在等待 I/O 請求的話,那么增加idle的時間。
所以,從上面的分析可知,要增加iowait的時間需要滿足以下兩個條件:
當前進程是idle進程,也就是說 CPU 處于空閑狀態(tài)。
有進程在等待 I/O 請求完成。
進一步說,當 CPU 處于iowait狀態(tài)時,說明 CPU 處于空閑狀態(tài),并且系統(tǒng)中有進程因為等待 I/O 請求而阻塞,也說明了 CPU 的利用率不夠充分。
這時,我們可以使用異步 I/O(如iouring)來優(yōu)化程序,使得進程不會被 I/O 請求阻塞。
審核編輯:劉清
-
cpu
+關(guān)注
關(guān)注
68文章
11226瀏覽量
223174 -
LINUX內(nèi)核
+關(guān)注
關(guān)注
1文章
318瀏覽量
23074 -
時鐘中斷
+關(guān)注
關(guān)注
0文章
4瀏覽量
8005
原文標題:系統(tǒng)性能分析之|iowait是什么?
文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
使用吉時利DMM的比率功能測量功率
如何在Linux使用iostat命令
linux統(tǒng)計文件個數(shù)
絕對輸出iMEMS陀螺儀與比率ADC的配合使用
算法大全_數(shù)據(jù)的統(tǒng)計描述和分析
RTD比率式溫度測量應用
小差比率制動系數(shù)校驗的優(yōu)化
加密貨幣交易中采用的夏普比率是什么
比特幣的庫存與流動比率分析
帶大家看看Linux內(nèi)核如何調(diào)度進程的
深入探究Linux系統(tǒng)噪音統(tǒng)計(osnoise tracer)

看看Linux是怎么統(tǒng)計iowait比率的?
評論