磁盤測試----fio


測試前提

我們在進行測試時,都會分清楚:

  • 測試對象:要區分硬盤、SSD、RAID、SAN、雲硬盤等,因為它們有不同的特點
  • 測試指標:IOPS和MBPS(吞吐率),下面會具體闡述
  • 測試工具:Linux下常用Fio、dd工具, Windows下常用IOMeter,
  • 測試參數: IO大小,尋址空間,隊列深度,讀寫模式,隨機/順序模式
  • 測試方法:也就是測試步驟。

測試是為了對比,所以需要定性和定量。在宣布自己的測試結果時,需要說明這次測試的工具、參數、方法,以便於比較。

存儲系統模型

為了更好的測試,我們需要先了解存儲系統,塊存儲系統本質是一個排隊模型,我們可以拿銀行作為比喻。還記得你去銀行辦事時的流程嗎?

  1. 去前台取單號
  2. 等待排在你之前的人辦完業務
  3. 輪到你去某個櫃台
  4. 櫃台職員幫你辦完手續1
  5. 櫃台職員幫你辦完手續2
  6. 櫃台職員幫你辦完手續3
  7. 辦完業務,從櫃台離開

如何評估銀行的效率呢:

  • 服務時間 = 手續1 + 手續2 + 手續3
  • 響應時間 = 服務時間 + 等待時間
  • 性能 = 單位時間內處理業務數量

那銀行如何提高效率呢:

  • 增加櫃台數
  • 降低服務時間

因此,排隊系統或存儲系統的優化方法是

  • 增加並行度
  • 降低服務時間

硬盤測試

硬盤原理

我們應該如何測試SATA/SAS硬盤呢?首先需要了解磁盤的構造,並了解磁盤的工作方式:

每個硬盤都有一個磁頭(相當於銀行的櫃台),硬盤的工作方式是:

  • 收到IO請求,得到地址和數據大小
  • 移動磁頭(尋址)
  • 找到相應的磁道(尋址)
  • 讀取數據
  • 傳輸數據

則磁盤的隨機IO服務時間:

服務時間 = 尋道時間 + 旋轉時間 + 傳輸時間

對於10000轉速的SATA硬盤來說,一般尋道時間是7 ms,旋轉時間是3 ms, 64KB的傳輸時間是 0.8 ms, 則SATA硬盤每秒可以進行隨機IO操作是 1000/(7 + 3 + 0.8) = 93,所以我們估算SATA硬盤64KB隨機寫的IOPS是93。一般的硬盤廠商都會標明順序讀寫的MBPS。
我們在列出IOPS時,需要說明IO大小,尋址空間,讀寫模式,順序/隨機,隊列深度。我們一般常用的IO大小是4KB,這是因為文件系統常用的塊大小是4KB。

使用dd測試硬盤

雖然硬盤的性能是可以估算出來的,但是怎么才能讓應用獲得這些性能呢?對於測試工具來說,就是如何得到IOPS和MBPS峰值。我們先用dd測試一下SATA硬盤的MBPS(吞吐量)。

#dd if=/dev/zero of=/dev/sdd bs=4k count=300000 oflag=direct

記錄了300000+0 的讀入 記錄了300000+0 的寫出 1228800000字節(1.2 GB)已復制,17.958 秒,68.4 MB/秒

#iostat -x sdd 5 10
...
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sdd 0.00 0.00 0.00 16794.80 0.00 134358.40 8.00 0.79 0.05 0.05 78.82
...

為什么這塊硬盤的MBPS只有68MB/s? 這是因為磁盤利用率是78%,沒有到達95%以上,還有部分時間是空閑的。當dd在前一個IO響應之后,在准備發起下一個IO時,SATA硬盤是空閑的。那么如何才能提高利用率,讓磁盤不空閑呢?只有一個辦法,那就是增加硬盤的隊列深度。相對於CPU來說,硬盤屬於慢速設備,所有操作系統會有給每個硬盤分配一個專門的隊列用於緩沖IO請求。

隊列深度

什么是磁盤的隊列深度?

在某個時刻,有N個inflight的IO請求,包括在隊列中的IO請求、磁盤正在處理的IO請求。N就是隊列深度。
加大硬盤隊列深度就是讓硬盤不斷工作,減少硬盤的空閑時間。
加大隊列深度 -> 提高利用率 -> 獲得IOPS和MBPS峰值 -> 注意響應時間在可接受的范圍內
增加隊列深度的辦法有很多
使用異步IO,同時發起多個IO請求,相當於隊列中有多個IO請求
多線程發起同步IO請求,相當於隊列中有多個IO請求
增大應用IO大小,到達底層之后,會變成多個IO請求,相當於隊列中有多個IO請求 隊列深度增加了。
隊列深度增加了,IO在隊列的等待時間也會增加,導致IO響應時間變大,這需要權衡。讓我們通過增加IO大小來增加dd的隊列深度,看有沒有效果:

dd if=/dev/zero of=/dev/sdd bs=2M count=1000 oflag=direct

記錄了1000+0 的讀入 記錄了1000+0 的寫出 2097152000字節(2.1 GB)已復制,10.6663 秒,197 MB/秒

Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sdd 0.00 0.00 0.00 380.60 0.00 389734.40 1024.00 2.39 6.28 2.56 97.42

可以看到2MB的IO到達底層之后,會變成多個512KB的IO,平均隊列長度為2.39,這個硬盤的利用率是97%,MBPS達到了197MB/s。(為什么會變成512KB的IO,你可以去使用Google去查一下內核參數 max_sectors_kb的意義和使用方法 )
也就是說增加隊列深度,是可以測試出硬盤的峰值的。

使用fio測試硬盤

現在,我們來測試下SATA硬盤的4KB隨機寫的IOPS。

$fio -ioengine=libaio -bs=4k -direct=1 -thread -rw=randwrite -size=1000G -filename=/dev/vdb 
-name="EBS 4K randwrite test" -iodepth=64 -runtime=60

簡單介紹fio的參數

ioengine: 負載引擎,我們一般使用libaio,發起異步IO請求。
bs: IO大小
direct: 直寫,繞過操作系統Cache。因為我們測試的是硬盤,而不是操作系統的Cache,所以設置為1。
rw: 讀寫模式,有順序寫write、順序讀read、隨機寫randwrite、隨機讀randread等。
size: 尋址空間,IO會落在 [0, size)這個區間的硬盤空間上。這是一個可以影響IOPS的參數。一般設置為硬盤的大小。
filename: 測試對象
iodepth: 隊列深度,只有使用libaio時才有意義。這是一個可以影響IOPS的參數。
runtime: 測試時長

下面我們做兩次測試,分別 iodepth = 1和iodepth = 4的情況。下面是iodepth = 1的測試結果。

上圖中藍色方框里面的是測出的IOPS 230, 綠色方框里面是每個IO請求的平均響應時間,大約是4.3ms。黃色方框表示95%的IO請求的響應時間是小於等於 9.920 ms。橙色方框表示該硬盤的利用率已經達到了98.58%。
下面是 iodepth = 4 的測試:

我們發現這次測試的IOPS沒有提高,反而IO平均響應時間變大了,是17ms。

為什么這里提高隊列深度沒有作用呢,原因當隊列深度為1時,硬盤的利用率已經達到了98%,說明硬盤已經沒有多少空閑時間可以壓榨了。而且響應時間為 4ms。 對於SATA硬盤,當增加隊列深度時,並不會增加IOPS,只會增加響應時間。這是因為硬盤只有一個磁頭,並行度是1, 所以當IO請求隊列變長時,每個IO請求的等待時間都會變長,導致響應時間也變長。

常見測試方法

#順序讀
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest

#順序寫
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest

#隨機讀
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest

#隨機寫
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest

#混合隨機讀寫
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=100 -group_reporting -name=mytest -ioscheduler=noop

結果分析


免責聲明!

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



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