我們對(duì)系統(tǒng)性能進(jìn)行優(yōu)化時(shí),一般會(huì)使用top命令來(lái)查看系統(tǒng)負(fù)載和系統(tǒng)中各個(gè)進(jìn)程的運(yùn)行情況,從而找出影響系統(tǒng)性能的因素。如下圖所示:
top
top命令會(huì)輸出很多系統(tǒng)相關(guān)的信息,如:系統(tǒng)負(fù)載、系統(tǒng)中的進(jìn)程數(shù)、CPU使用率和內(nèi)存使用率等,這些信息對(duì)排查系統(tǒng)性能問(wèn)題起著至關(guān)重要的作用。
本文主要介紹top命令中的iowait指標(biāo)(如上圖中紅色方框所示)的含義和作用。
什么是iowait
什么是iowait?我們來(lái)看看 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 請(qǐng)求完成時(shí),處于空閑狀態(tài)的時(shí)間百分比(此時(shí)正在運(yùn)行著idle進(jìn)程)。
可以看出,如果系統(tǒng)處于iowait狀態(tài),那么必須滿足以下兩個(gè)條件:
系統(tǒng)中存在等待 I/O 請(qǐng)求完成的進(jìn)程。
系統(tǒng)當(dāng)前正處于空閑狀態(tài),也就是說(shuō)沒(méi)有可運(yùn)行的進(jìn)程。
iowait統(tǒng)計(jì)原理
既然我們知道了iowait的含義,那么接下來(lái)看看 Linux 是怎么統(tǒng)計(jì)iowait的比率的。
Linux 會(huì)把iowait占用的時(shí)間輸出到/proc/stat文件中,我們可以通過(guò)一下命令來(lái)獲取到iowait占用的時(shí)間:
cat/proc/stat
命令輸出如下圖所示:
stat
紅色方框中的數(shù)據(jù)就是iowait占用的時(shí)間。
我們可以每隔一段時(shí)間讀取一次/proc/stat文件,然后把兩次獲取到的iowait時(shí)間進(jìn)行相減,得到的結(jié)果是這段時(shí)間內(nèi),CPU處于iowait狀態(tài)的時(shí)間。接著再將其除以總時(shí)間,得到iowait占用總時(shí)間的比率。
現(xiàn)在我們來(lái)看看/proc/stat文件是怎樣獲取iowait的時(shí)間的。
在內(nèi)核中,每個(gè) CPU 都有一個(gè)cpu_usage_stat結(jié)構(gòu),主要用于統(tǒng)計(jì) 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)的時(shí)間。
所以要獲取系統(tǒng)處于iowait狀態(tài)的總時(shí)間,只需要將所有 CPU 的iowait時(shí)間相加即可,代碼如下(位于源文件fs/proc/stat.c):
staticintshow_stat(structseq_file*p,void*v) { u64iowait; ... //1.遍歷系統(tǒng)中的所有CPU for_each_possible_cpu(i){ ... //2.獲取CPU對(duì)應(yīng)的iowait時(shí)間,并相加 iowait=cputime64_add(iowait,kstat_cpu(i).cpustat.iowait); ... } ... return0; }
show_stat()函數(shù)首先會(huì)遍歷所有 CPU,然后讀取其iowait時(shí)間,并且將它們相加。
增加iowait時(shí)間
從上面的分析可知,每個(gè) CPU 都有一個(gè)用于統(tǒng)計(jì)iowait時(shí)間的計(jì)數(shù)器,那么什么時(shí)候會(huì)增加這個(gè)計(jì)數(shù)器呢?
答案是:系統(tǒng)時(shí)鐘中斷。
在系統(tǒng)時(shí)鐘中斷中,會(huì)調(diào)用account_process_tick()函數(shù)來(lái)更新 CPU 的時(shí)間,代碼如下:
voidaccount_process_tick(structtask_struct*p,intuser_tick) { cputime_tone_jiffy_scaled=cputime_to_scaled(cputime_one_jiffy); structrq*rq=this_rq(); //1.如果當(dāng)前進(jìn)程處于用戶態(tài),那么增加用戶態(tài)的CPU時(shí)間 if(user_tick){ account_user_time(p,cputime_one_jiffy,one_jiffy_scaled); } //2.如果前進(jìn)程處于內(nèi)核態(tài),并且不是idle進(jìn)程,那么增加內(nèi)核態(tài)CPU時(shí)間 elseif((p!=rq->idle)||(irq_count()!=HARDIRQ_OFFSET)){ account_system_time(p,HARDIRQ_OFFSET,cputime_one_jiffy, one_jiffy_scaled); } //3.如果當(dāng)前進(jìn)程是idle進(jìn)程,那么調(diào)用account_idle_time()函數(shù)進(jìn)行處理 else{ account_idle_time(cputime_one_jiffy); } }
我們主要關(guān)注當(dāng)前進(jìn)程是idle進(jìn)程的情況,這是內(nèi)核會(huì)調(diào)用account_idle_time()函數(shù)進(jìn)行處理,其代碼如下:
voidaccount_idle_time(cputime_tcputime) { structcpu_usage_stat*cpustat=&kstat_this_cpu.cpustat; cputime64_tcputime64=cputime_to_cputime64(cputime); structrq*rq=this_rq(); //1.如果當(dāng)前有進(jìn)程在等待IO請(qǐng)求的話,那么增加iowait的時(shí)間 if(atomic_read(&rq->nr_iowait)>0){ cpustat->iowait=cputime64_add(cpustat->iowait,cputime64); } //2.否則增加idle的時(shí)間 else{ cpustat->idle=cputime64_add(cpustat->idle,cputime64); } }
account_idle_time()函數(shù)的邏輯比較簡(jiǎn)單,主要分以下兩種情況進(jìn)行處理:
如果當(dāng)前有進(jìn)程在等待 I/O 請(qǐng)求的話,那么增加iowait的時(shí)間。
如果當(dāng)前沒(méi)有進(jìn)程在等待 I/O 請(qǐng)求的話,那么增加idle的時(shí)間。
所以,從上面的分析可知,要增加iowait的時(shí)間需要滿足以下兩個(gè)條件:
當(dāng)前進(jìn)程是idle進(jìn)程,也就是說(shuō) CPU 處于空閑狀態(tài)。
有進(jìn)程在等待 I/O 請(qǐng)求完成。
進(jìn)一步說(shuō),當(dāng) CPU 處于iowait狀態(tài)時(shí),說(shuō)明 CPU 處于空閑狀態(tài),并且系統(tǒng)中有進(jìn)程因?yàn)榈却?I/O 請(qǐng)求而阻塞,也說(shuō)明了 CPU 的利用率不夠充分。
這時(shí),我們可以使用異步 I/O(如iouring)來(lái)優(yōu)化程序,使得進(jìn)程不會(huì)被 I/O 請(qǐng)求阻塞。
審核編輯:劉清
-
cpu
+關(guān)注
關(guān)注
68文章
10898瀏覽量
212564 -
LINUX內(nèi)核
+關(guān)注
關(guān)注
1文章
316瀏覽量
21697 -
時(shí)鐘中斷
+關(guān)注
關(guān)注
0文章
4瀏覽量
7715
原文標(biāo)題:系統(tǒng)性能分析之|iowait是什么?
文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛(ài)好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論