SSD測試第一神器——FIO

原創內容,轉載請注明:  [http://www.od-music.com]  謝謝!

對于SSD性能測試來說,最好的工具莫過于FIO了。

?


上面這個可愛的小伙子名字叫Jens Axboe,他是丹麥哥本哈根大學計算機系沒畢業的學生,他還有一個有名的同鄉叫Linus,沒想到老鄉后來也成了他的領導。Jens今年(2017年)40歲,16歲開始就接觸Linux,后來也成了Linux開發者,現在是Linux Kernel大拿了,負責塊設備層的維護。這個塊設備層就是跟我們SSD關系最緊密的層級,聯系了上層文件系統和下層設備驅動程序。他開發了不少有用的程序,比如Linux IO Scheduler里面的Deadline, CFQ Scheduler,還有著名的王牌測試工具FIO。 Jens曾經在Fusion-IO、Oracle等公司工作,現在在Facebook,阿呆聽說在硅谷Facebook給碼農的薪水是最高的。

?

FIO是Jens開發的一個開源測試工具,功能非常強大,本文就只介紹其中一些基本功能。

?

線程,隊列深度,Offset,同步異步,DirectIO,BIO

?

使用FIO之前,首先要有一些SSD性能測試的基礎知識。

?

線程指的是同時有多少個讀或寫任務在并行執行,一般來說,CPU里面的一個核心同一時間只能運行一個線程。如果只有一個核心,要想運行多線程,只能使用時間切片,每個線程跑一段時間片,所有線程輪流使用這個核心。Linux使用Jiffies來代表一秒鐘被劃分成了多少個時間片,一般來說Jiffies是1000或100,所以時間片就是1毫秒或10毫秒。

?

一般電腦發送一個讀寫命令到SSD只需要幾微秒,但是SSD要花幾百微秒甚至幾毫秒才能執行完這個命令。如果發一個讀寫命令,然后線程一直休眠,等待結果回來才喚醒處理結果,這種叫做同步模式??梢韵胂?,同步模式是很浪費SSD性能的,因為SSD里面有很多并行單元,比如一般企業級SSD內部有8-16個數據通道,每個通道內部有4-16個并行邏輯單元(LUN,Plane),所以同一時間可以執行32-256個讀寫命令。同步模式就意味著,只有其中一個并行單元在工作,暴殄天物。

?

為了提高并行性,大部分情況下SSD讀寫采用的是異步模式。就是用幾微秒發送命令,發完線程不會傻傻的在那里等,而是繼續發后面的命令。如果前面的命令執行完了,SSD通知會通過中斷或者輪詢等方式告訴CPU,CPU來調用該命令的回調函數來處理結果。這樣的好處是,SSD里面幾十上百個并行單元大家都能分到活干,效率暴增。

?

不過,在異步模式下,CPU不能一直無限的發命令到SSD。比如SSD執行讀寫如果發生了卡頓,那有可能系統會一直不停的發命令,幾千個,甚至幾萬個,這樣一方面SSD扛不住,另一方面這么多命令會很占內存,系統也要掛掉了。這樣,就帶來一個參數叫做隊列深度。舉個例子,隊列深度64就是說,系統發的命令都發到一個大小為64的隊列,如果填滿了就不能再發。等前面的讀寫命令執行完了,隊列里面空出位置來,才能繼續填命令。

?

一個SSD或者文件有大小,測試讀寫的時候設置Offset就可以從某個偏移地址開始測試。比如從offset=4G的偏移地址開始。

?

Linux讀寫的時候,內核維護了緩存,數據先寫到緩存,后面再后臺寫到SSD。讀的時候也優先讀緩存里的數據。這樣速度可以加快,但是一旦掉電緩存里的數據就沒了。所以有一種模式叫做DirectIO,跳過緩存,直接讀寫SSD。

?

Linux讀寫SSD等塊設備使用的是BIO,Block-IO,這是個數據結構,包含了數據塊的邏輯地址LBA,數據大小和內存地址等。

?

FIO初體驗

?

一般Linux系統是自帶FIO的,如果沒有或者版本太老,要自己從https://github.com/axboe/fio 下載最新版本源代碼編譯安裝。進入代碼主目錄,輸入下列命令就編譯安裝好了。

./configure;make && make install

?

幫助文檔用下面命令查看:

man fio

?

先來看一個簡單的例子:

fio -rw=randwrite? -ioengine=libaio -direct=1 –thread –numjobs=1? -iodepth=64 -filename=/dev/sdb4  -size=10G -name=job1 -offset=0MB -bs=4k -name=job2 -offset=10G -bs=512 --output TestResult.log

?

每一項的意思都可以從fio幫助文檔是:

fio:軟件名稱。

-rw=randwrite:讀寫模式,randwrite是隨機寫測試,還有順序讀read,順序寫write,隨機讀randread,混合讀寫等。

-ioengine=libaio:libaio指的是異步模式,如果是同步就要用sync。

-direct=1:是否使用directIO。

-thread:使用pthread_create創建線程,另一種是fork創建進程。進程的開銷比線程要大,一般都采用thread測試。

–numjobs=1:每個job是1個線程,這里用了幾,后面每個用-name指定的任務就開幾個線程測試。所以最終線程數=任務數* numjobs。

-iodepth=64:隊列深度64.

-filename=/dev/sdb4:數據寫到/dev/sdb4這個盤(塊設備)。這里可以是一個文件名,也可以是分區或者SSD。

-size=10G:每個線程寫入數據量是10GB。

-name=job1:一個任務的名字,名字隨便起,重復了也沒關系。這個例子指定了job1和job2,建立了兩個任務,共享-name=job1之前的參數。-name之后的就是這個任務獨有的參數。

-offset=0MB:從偏移地址0MB開始寫。

-bs=4k:每一個BIO命令包含的數據大小是4KB。一般4KB IOPS測試,就是在這里設置。

–output TestResult.log:日志輸出到TestResult.log。

?

FIO結果解析

?

我們來看一個FIO測試隨機讀的結果。命令如下,2個任務并行測試,隊列深度64,異步模式,每個任務測試數據1GB,每個數據塊4KB。所以,這個命令是在測試兩個線程、隊列深度64下的4KB隨機讀IOPS。

?

# fio -rw=randread -ioengine=libaio -direct=1  -iodepth=64 -filename=/dev/sdc -size=1G -bs=4k -name=job1 -offset=0G -name=job2 -offset=10G

job1: (g=0): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64

job2: (g=0): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64

fio-2.13

Starting 2 processes

Jobs: 2 (f=2)

job1: (groupid=0, jobs=1): err= 0: pid=27752: Fri Jul 28 14:16:50 2017

  read : io=1024.0MB, bw=392284KB/s, iops=98071, runt=  2673msec

    slat (usec): min=6, max=79, avg= 9.05, stdev= 2.04

    clat (usec): min=148, max=1371, avg=642.89, stdev=95.08

     lat (usec): min=157, max=1380, avg=651.94, stdev=95.16

    clat percentiles (usec):

     |  1.00th=[  438],  5.00th=[  486], 10.00th=[  516], 20.00th=[  564],

     | 30.00th=[  596], 40.00th=[  620], 50.00th=[  644], 60.00th=[  668],

     | 70.00th=[  692], 80.00th=[  724], 90.00th=[  756], 95.00th=[  796],

     | 99.00th=[  884], 99.50th=[  924], 99.90th=[ 1004], 99.95th=[ 1048],

     | 99.99th=[ 1144]

    lat (usec) : 250=0.01%, 500=6.82%, 750=81.14%, 1000=11.93%

    lat (msec) : 2=0.11%

  cpu          : usr=9.09%, sys=90.08%, ctx=304, majf=0, minf=98

  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%

     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%

     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%

     issued    : total=r=262144/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0

     latency   : target=0, window=0, percentile=100.00%, depth=64

job2: (groupid=0, jobs=1): err= 0: pid=27753: Fri Jul 28 14:16:50 2017

  read : io=1024.0MB, bw=447918KB/s, iops=111979, runt=  2341msec

    slat (usec): min=5, max=41, avg= 6.30, stdev= 0.79

    clat (usec): min=153, max=1324, avg=564.61, stdev=100.40

     lat (usec): min=159, max=1331, avg=570.90, stdev=100.41

    clat percentiles (usec):

     |  1.00th=[  354],  5.00th=[  398], 10.00th=[  430], 20.00th=[  474],

     | 30.00th=[  510], 40.00th=[  540], 50.00th=[  572], 60.00th=[  596],

     | 70.00th=[  620], 80.00th=[  644], 90.00th=[  684], 95.00th=[  724],

     | 99.00th=[  804], 99.50th=[  844], 99.90th=[  932], 99.95th=[  972],

     | 99.99th=[ 1096]

    lat (usec) : 250=0.03%, 500=27.57%, 750=69.57%, 1000=2.79%

    lat (msec) : 2=0.04%

  cpu          : usr=11.62%, sys=75.60%, ctx=35363, majf=0, minf=99

  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%

     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%

     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%

     issued    : total=r=262144/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0

     latency   : target=0, window=0, percentile=100.00%, depth=64

?

Run status group 0 (all jobs):

   READ: io=2048.0MB, aggrb=784568KB/s, minb=392284KB/s, maxb=447917KB/s, mint=2341msec, maxt=2673msec

?

Disk stats (read/write):

  sdc: ios=521225/0, merge=0/0, ticks=277357/0, in_queue=18446744073705613924, util=100.00%

?

FIO會為每個Job打印統計信息。最后面是合計的數值。我們一般看重的總的性能和延遲。

?

首先看的是最后總的帶寬,aggrb=784568KB/s,算成4KB就是196K IOPS。

?

再來看看延遲Latency。Slat是發命令時間,slat (usec): min=6, max=79, avg= 9.05, stdev= 2.04說明最短時間6微秒,最長79微秒,平均9微秒,標準差2.04。clat是命令執行時間,lat就是總的延遲??吹贸鰜?,讀的平均延遲在571微秒左右。

?

clat percentiles (usec)給出了延遲的統計分布。比如90.00th=[ 684]說明90%的讀命令延遲都在684微秒以內。

?

用FIO做數據校驗

?

用FIO可以檢驗寫入數據是否出錯。用-verify=str來選擇校驗算法,有md5 crc16 crc32 crc32c crc32c-intel crc64 crc7 sha256 sha512 sha1等。為了校驗,需要用do_verify參數。如果是寫,那么do_verify=1就意味著寫完再讀校驗,這種會很占內存,因為FIO會把每個數據塊的校驗數據保存在內存里。do_verify=0時只寫校驗數據,不做讀校驗。

?

讀的時候do_verify=1,那么讀出來的數據都會做校驗值檢查,do_verify=0的話,只讀數據,不做檢查。

?

另外,verify=meta時,fio會在數據塊內寫入時間戳、邏輯地址等,此時還能verify_pattern指定寫入數據pattern。

?

FIO其他功能

?

FIO功能非常強大,可以通過man來查看每一個功能,也有網頁版幫助文檔https://linux.die.net/man/1/fio。

?

FIO配置文件

?

前面的例子都是用命令行來測試,其實也可以用配置文件把這些參數寫進去。比如新建FIO配置文件test.log內容如下:

?

[global]

filename=/dev/sdc

direct=1

iodepth=64

thread

rw=randread

ioengine=libaio

bs=4k

numjobs=1 

size=10G

?

[job1]

name=job1

offset=0

?

[job2]

name=job2

offset=10G

?

;--end job file

?

保存后,只需要fio test.log就能執行測試任務了。是不是很方便?

分類目錄 SSD.
掃一掃二維碼或者微信搜索公眾號ssdfans關注(添加朋友->點最下面的公眾號->搜索ssdfans),可以經??吹絊SD技術和產業的文章(SSD Fans只推送干貨)。
ssdfans微信群介紹
技術討論群 覆蓋2000多位中國和世界華人圈SSD以及存儲技術精英
固件、軟件、測試群 固件、軟件和測試技術討論
異構計算群 討論人工智能和GPU、FPGA、CPU異構計算
ASIC-FPGA群 芯片和FPGA硬件技術討論群
閃存器件群 NAND、3D XPoint等固態存儲介質技術討論
企業級 企業級SSD、企業級存儲
銷售群 全國SSD供應商都在這里,砍砍價,會比某東便宜20%
工作求職群 存儲行業換工作,發招聘,要關注各大公司招聘信息,趕快來
高管群 各大SSD相關存儲公司高管和創始人、投資人

想加入這些群,請微信掃描下面二維碼,或搜索nanoarchplus,加阿呆為微信好友,介紹你的昵稱-單位-職務,注明群名,拉你進群。SSD業界需要什么幫助,也可以找阿呆聊。