add by zhj: wa是指當CPU空閑且磁盤IO阻塞的時間占比。注意這里只統計磁盤IO(包含NFS類型的磁盤),不包含網絡IO
原文:https://baijiahao.baidu.com/s?id=1641356547223820839&wfr=spider&for=pc
作者:IT劉小虎
最近在做連續數據流的緩沖系統,C語言代碼實現后,粗略測試了下,功能上應該沒有問題。那么,接下來就該測試性能了。輸入 top 命令,的確可以看到一系列 cpu 使用率,其中一個值得注意的子項就是 io 使用率了,如下圖:
上圖中 io 前面的數字是什么意思呢?是指 CPU 有 63% 的時間花費在 io 上了嗎?在 Linux 中輸入 man 命令查看相關手冊,發現 io(wait) 被解釋為“等待 I/O 完成的時間”。

如果按照手冊對 iowait 字面上的解釋,是很容易陷入誤區的。因為就上例而言,似乎 CPU 有 63% 的時間消耗在等待I/O 操作完成,導致 CPU 的性能白白浪費這么多。
其實不是的,Linux 是一個成熟的操作系統,它才不會讓 CPU 寶貴的性能白白浪費在耗時的 I/O 等待上,實際上,如果當前系統還有其他任務需要使用 CPU,Linux 會將等待 I/O 完成的任務暫時掛起,將 CPU 使用權暫時交給有需要的任務。
那么 iowait 到底是什么意思呢?
有人認為,iowait 只是 CPU 空閑(idle)時間的一個子集,也就是說 iowait 其實可以歸類到 idle 狀態,本質上表示 CPU 是空閑的,只不過 iowait 表示任務中有等待 I/O 操作完成的時間。
這樣認為有一定的道理,畢竟哪怕 iowait 的數值是 100%,也僅僅是說明是 CPU 把時間都花在“等待”上了,這樣的情況一般只有在當前系統沒有其他任務需要使用 CPU 時才會發生。因為一旦有其他任務需要使用 CPU,Linux 內核會立刻將 CPU 提供給該任務使用,CPU 時間就不再全部是“等待I/O”花費的了(不再是 100% io 了)。
不過讀者應該明白的是,“idle”是 CPU 的狀態,而 “iowait”則是任務的狀態。對於單核 CPU 來說,同時只能有一個任務運行,上述說法可以認為是准確的。但是對於多核 CPU 來說,情況就有些不同了。
例如,某個系統擁有 4 個 CPU,有一個 I/O 超密集型任務正在運行,那么,iowait 會是 100% 呢,還是 25% 呢?換句話說,iowait 會是在其中一個 CPU 上 100%,其他CPU 上 0% 呢,還是會在 4 個 CPU 上平均 25 % 呢?
簡單做一個實驗就可以了。我們使用 Linux 中的 dd 命令模擬高密集 I/O 任務,這一過程可以通過輸入以下命令實現:
dd if=/dev/sda of=/dev/null bs=1MB
這條命令可能需要 root 權限,/dev/sda 是我的磁盤,讀者可能需要換成自己的節點名。
此時,通過 top 命令可以查看到下面這樣的結果:
圖中的 “wa”表示 I/O 等待時間(它和 io、iowait 是一個意思,名字不同而已)。可見,Linux 此時采用單個 CPU 處理 I/O 任務。如果讀者細心的話,應該能夠發現,I/O 任務只是偶爾的切換到其他 CPU 上運行,這是為了保證 CPU 緩沖的命中率,Linux 內核盡量讓任務在單個 CPU 中運行。
在其他一些系統中,I/O 任務可能會在各個CPU中頻繁的切換,此時會產生下面這樣的結果:
假設 dd 命令是系統中執行 I/O 的唯一任務,那么在同一時刻,最多只會有一個 CPU 處理 I/O 等待任務。因此,實際上 34.8+20.9+26.7+3.7=86.1,接近但低於100。
進一步實驗
為了讓實驗更可重現,我們可以使用 taskset 命令為任務指定 CPU:
taskset 1 dd if=/dev/sda of=/dev/null bs=1MB
應該注意,taskset 后的數字 1 並不是 CPU 的編號,而是一種掩碼。
此時通過 top 命令查看 CPU 使用請看,應該能夠發現 CPU0 的 wa 項接近 100,這說明 CPU0 幾乎所有的時間都花在等待 I/O 操作完成上。那么,是不是此時 CPU 就沒有精力處理其他任務了呢?我們再輸入下面這條命令:
taskset 1 sh -c "while true; do true; done"
上面這條命令是在相同的 CPU 上執行一個死循環,用於模擬計算密集型任務,它是不是就沒有機會執行了呢?輸入 top 命令,得到如下結果:
CPU0 的 wa 降低為 0 了,與此同時,用戶態和系統態的 CPU 時間接近 100% 了。這是意料之中的,因為 I/O 等待時間只是 idle 時間的子項,本質上 CPU 是空閑的,Linux 內核當然可以把 CPU 交給第二個任務使用。原本用於等待 I/O 完成的 CPU 時間,現在用於處理第二個任務了。此時通過 top 命令查看 wa,自然得到接近 0 的結果。
小結
現在基本就清楚 top 命令中 % io 的含義了:對於指定的 CPU 來說,iowait 表示在此時間內,CPU 其實是空閑的,不過 CPU 並不是嚴格意義上的“空閑”,畢竟它還需要等待 I/O 操作完成。對於產生 I/O 操作請求的線程來說,它會阻塞等待 I/O 操作完成。理解這一點,對於我們開發I/O操作密集的C語言程序是非常有幫助的。