原創:打碼日記(微信公眾號ID:codelogs),歡迎分享,轉載請保留出處。
簡介
一直以來,我都知道top、vmstat、mpstat中有一個叫wa(%iowait)的cpu指標,但對它表示的具體含義又不是很清楚,故專門去網上學習了一下。
iowait在man中的介紹
man文檔是學習命令的第一手資料,先來看看man文檔中的介紹,如下:
$ man top
wa, IO-wait : time waiting for I/O completion.
$ man vmstat
wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle.
$ man mpstat
%iowait
Show the percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request.
$ man iostat
%iowait
Show the percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request.
$ man sar
%iowait
Percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request.
翻譯過來就是CPU空閑且有正在進行的磁盤IO的情況下所占的時間比例
,理解起來非常模糊,只能大概了解到這個指標好像和磁盤IO有關。
iowait真相
在man中查不到,那就只能去網上找找了,看有沒有大佬在網上分享過這方面知識,在經過好一段時間的baidu、google,終於發現了如下兩篇文章:
- The precise meaning of I/O wait time in Linux ,英文的講解,並含有一些命令實踐。
- Linux Kernel iowait 時間的代碼原理,從內核代碼層面講解。
可以說這兩篇文章介紹得非常清楚了,我用白話概括一下內核處理過程,如下:
- 我們知道操作系統給每個CPU分配了一個運行隊列rq,用於存放可運行的線程task_stuct,調度器每次都是從此隊列中取線程執行,若隊列為空則CPU執行內核空閑線程的代碼。
- 當線程執行io操作時,需要將當前任務切換出去,會先將當前線程
task_stuct.in_iowait
設置為1,線程狀態設置為TASK_UNINTERRUPTIBLE
(D狀態),並將運行隊列上rq.nr_iowait
加1,而io完成后task_stuct.in_iowait
還原為0,rq.nr_iowait
減1,具體見內核io_schedule_timeout
函數,可見rq.nr_iowait
代表當前CPU上等待io操作的線程數量。 - 當CPU執行內核空閑代碼時,會判斷
rq.nr_iowait
,若大於0則將空閑時間計算在iowait上,否則計算在idle上,具體見內核account_idle_time
函數。
總結一下idle與iowait區別,如下:
- iowait時間實際上就是CPU空閑時間,Linux上空閑時間有兩類,一類是普通的idle,另一類是iowait。
- 普通idle與iowait區別是,iowait是CPU空閑時,有任務正在做磁盤io操作,而idle則沒有。
iowait高代表io壓力大?
iowait指標是從CPU角度看io,但畢竟不是從io層面看的,所以iowait高也不一定代表有問題,如下:
- 如果程序遷移到性能更好的CPU上,由於CPU運行代碼變快,會導致空閑時間變多,而iowait時間實際上就是空閑時間,所以有時會發現,性能更好的機器上iowait反而更高了。
- 比如有這樣兩個程序,程序A在10s內每1s都做1次io操作,假設io操作需要1s,那么10s內的iowait是100%,而程序的IOPS是1。另一程序B在10s的前1s內並發執行了10次io操作,那么iowait是10%,而程序的峰值IOPS是10。雖然例子比較極端,但這里很明顯程序B的IOPS峰值更高,但它的iowait卻更低。
雖說iowait並不能准確反映io情況,但它也不是完全沒用的,在大多數情況下,iowait高確實代表了io壓力大,並且它至少提示了你應該進一步檢查一下io情況,這方面iostat、iotop、blktrace等可以做到。
另外,從上面的iowait原理中你會發現,處在iowait的線程,其必定是D狀態的(TASK_UNINTERRUPTIBLE),這在之前也提到過,D狀態是會影響系統負載的,詳細可查看 Linux命令拾遺-理解系統負載
命令實踐
stress -d
命令可以模擬做大量的磁盤操作,並使用taskset將stress綁定到3號核上運行,如下:
$ taskset --cpu-list 3 stress -d 1 --hdd-bytes 100G
stress: info: [9160] dispatching hogs: 0 cpu, 0 io, 0 vm, 1 hdd
然后使用mpstat -P ALL 1
觀察iowait情況,發現3號核iowait高達88%,如下:
然后新開一個shell窗口,使用stress -c
命令模擬大量的CPU運算,也使用taskset綁定到3號核上運行,如下:
$ taskset --cpu-list 3 stress -c 1
stress: info: [9178] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
再次使用mpstat -P ALL 1
觀察iowait情況,發現3號核iowait變成了0%,而%usr幾乎滿載,如下:
如果你理解了上面的內容,就能理解這個示例了。
第一次因為只有stress -d
在做io操作,所以CPU基本都是空閑的,而空閑期間基本都是有在做io的任務存在的,所以iowait高。
第二次因為加入stress -c
使得CPU不再空閑,而iowait實際上就是空閑時間,所以iowait自然就變成0了。
當然,如果你有興趣,還可以試下這兩個命令,它們可以將%sys
、%nice
變成100%,如下:
# 使得%sys滿載
$ taskset --cpu-list 3 dd if=/dev/zero of=/dev/null bs=1M count=1000000
# 使得%nice滿載
$ taskset --cpu-list 3 nice -n 19 stress -c 1
本系列文章索引
Linux命令拾遺-入門篇
Linux命令拾遺-文本處理篇
Linux命令拾遺-軟件資源觀測
Linux命令拾遺-硬件資源觀測
Linux命令拾遺-剖析工具
Linux命令拾遺-動態追蹤工具
Linux命令拾遺-理解系統負載
Linux命令拾遺-top中的%nice是啥
Linux命令拾遺-網絡抓包工具
Linux命令拾遺-查看系統信息
Linux命令拾遺-常用的輔助開發類命令
往期內容
字符編碼解惑
hex,base64,urlencode編碼方案對比
mysql的timestamp會存在時區問題?
真正理解可重復讀事務隔離級別
不容易自己琢磨出來的正則表達式用法