Linux命令拾遺-%iowait指標代表了什么?


原創:打碼日記(微信公眾號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,終於發現了如下兩篇文章:

可以說這兩篇文章介紹得非常清楚了,我用白話概括一下內核處理過程,如下:

  1. 我們知道操作系統給每個CPU分配了一個運行隊列rq,用於存放可運行的線程task_stuct,調度器每次都是從此隊列中取線程執行,若隊列為空則CPU執行內核空閑線程的代碼。
  2. 當線程執行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操作的線程數量。
  3. 當CPU執行內核空閑代碼時,會判斷rq.nr_iowait,若大於0則將空閑時間計算在iowait上,否則計算在idle上,具體見內核account_idle_time函數。

總結一下idle與iowait區別,如下:

  1. iowait時間實際上就是CPU空閑時間,Linux上空閑時間有兩類,一類是普通的idle,另一類是iowait。
  2. 普通idle與iowait區別是,iowait是CPU空閑時,有任務正在做磁盤io操作,而idle則沒有。

iowait高代表io壓力大?

iowait指標是從CPU角度看io,但畢竟不是從io層面看的,所以iowait高也不一定代表有問題,如下:

  1. 如果程序遷移到性能更好的CPU上,由於CPU運行代碼變快,會導致空閑時間變多,而iowait時間實際上就是空閑時間,所以有時會發現,性能更好的機器上iowait反而更高了。
  2. 比如有這樣兩個程序,程序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%,如下:
mpstat_iowait

然后新開一個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幾乎滿載,如下:
mpstat_iowait_0

如果你理解了上面的內容,就能理解這個示例了。
第一次因為只有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會存在時區問題?
真正理解可重復讀事務隔離級別
不容易自己琢磨出來的正則表達式用法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM