http://linuxperf.com/?p=156
iostat(1)是在Linux系統(tǒng)上查看I/O性能最基本的工具腹缩,然而對(duì)于那些熟悉其它UNIX系統(tǒng)的人來說它是很容易被誤讀的灼捂。比如在HP-UX上 avserv(相當(dāng)于Linux上的 svctm)是最重要的I/O指標(biāo)渴丸,反映了硬盤設(shè)備的性能恶守,它是指I/O請(qǐng)求從SCSI層發(fā)出养晋、到I/O完成之后返回SCSI層所消耗的時(shí)間温兼,不包括在SCSI隊(duì)列中的等待時(shí)間,所以avserv體現(xiàn)了硬盤設(shè)備處理I/O的速度帖族,又被稱為disk service time义矛,如果avserv很大,那么肯定是硬件出問題了盟萨。然而Linux上svctm的含義截然不同凉翻,事實(shí)上在iostat(1)和sar(1)的man page上都說了不要相信svctm,該指標(biāo)將被廢棄:
“Warning! Do not?trust this field any more. This field will be removed in?a future sysstat version.”
在Linux上捻激,每個(gè)I/O的平均耗時(shí)是用await表示的制轰,但它不能反映硬盤設(shè)備的性能,因?yàn)閍wait不僅包括硬盤設(shè)備處理I/O的時(shí)間胞谭,還包括了在隊(duì)列中等待的時(shí)間垃杖。I/O請(qǐng)求在隊(duì)列中的時(shí)候尚未發(fā)送給硬盤設(shè)備,即隊(duì)列中的等待時(shí)間不是硬盤設(shè)備消耗的丈屹,所以說await體現(xiàn)不了硬盤設(shè)備的速度调俘,內(nèi)核的問題比如I/O調(diào)度器什么的也有可能導(dǎo)致await變大。那么有沒有哪個(gè)指標(biāo)可以衡量硬盤設(shè)備的性能呢旺垒?非常遺憾的是彩库,iostat(1)和sar(1)都沒有,這是因?yàn)樗鼈兯蕾嚨?proc/diskstats不提供這項(xiàng)數(shù)據(jù)先蒋。要真正理解iostat的輸出結(jié)果骇钦,應(yīng)該從理解/proc/diskstats開始。
/proc/diskstats有11個(gè)字段竞漾,以下內(nèi)核文檔解釋了它們的含義https://www.kernel.org/doc/Documentation/iostats.txt眯搭,我重新表述了一下,注意除了字段#9之外都是累計(jì)值业岁,從系統(tǒng)啟動(dòng)之后一直累加:
(rd_ios)讀操作的次數(shù)鳞仙。
(rd_merges)合并讀操作的次數(shù)。如果兩個(gè)讀操作讀取相鄰的數(shù)據(jù)塊時(shí)笔时,可以被合并成一個(gè)棍好,以提高效率。合并的操作通常是I/O scheduler(也叫elevator)負(fù)責(zé)的糊闽。
(rd_sectors)讀取的扇區(qū)數(shù)量梳玫。
(rd_ticks)讀操作消耗的時(shí)間(以毫秒為單位)爹梁。每個(gè)讀操作從__make_request()開始計(jì)時(shí)右犹,到end_that_request_last()為止,包括了在隊(duì)列中等待的時(shí)間姚垃。
(wr_ios)寫操作的次數(shù)念链。
(wr_merges)合并寫操作的次數(shù)。
(wr_sectors)寫入的扇區(qū)數(shù)量。
(wr_ticks)寫操作消耗的時(shí)間(以毫秒為單位)掂墓。
(in_flight)當(dāng)前未完成的I/O數(shù)量谦纱。在I/O請(qǐng)求進(jìn)入隊(duì)列時(shí)該值加1,在I/O結(jié)束時(shí)該值減1君编。
注意:是I/O請(qǐng)求進(jìn)入隊(duì)列時(shí)跨嘉,而不是提交給硬盤設(shè)備時(shí)。
(io_ticks)該設(shè)備用于處理I/O的自然時(shí)間(wall-clock time)吃嘿。
請(qǐng)注意io_ticks與rd_ticks(字段#4)和wr_ticks(字段#8)的區(qū)別祠乃,rd_ticks和wr_ticks是把每一個(gè)I/O所消耗的時(shí)間累加在一起,因?yàn)橛脖P設(shè)備通扯以铮可以并行處理多個(gè)I/O亮瓷,所以rd_ticks和wr_ticks往往會(huì)比自然時(shí)間大。而io_ticks表示該設(shè)備有I/O(即非空閑)的時(shí)間降瞳,不考慮I/O有多少嘱支,只考慮有沒有。在實(shí)際計(jì)算時(shí)挣饥,字段#9(in_flight)不為零的時(shí)候io_ticks保持計(jì)時(shí)除师,字段#9(in_flight)為零的時(shí)候io_ticks停止計(jì)時(shí)。
(time_in_queue)對(duì)字段#10(io_ticks)的加權(quán)值扔枫。字段#10(io_ticks)是自然時(shí)間馍盟,不考慮當(dāng)前有幾個(gè)I/O,而time_in_queue是用當(dāng)前的I/O數(shù)量(即字段#9 in-flight)乘以自然時(shí)間茧吊。雖然該字段的名稱是time_in_queue贞岭,但并不真的只是在隊(duì)列中的時(shí)間,其中還包含了硬盤處理I/O的時(shí)間搓侄。iostat在計(jì)算avgqu-sz時(shí)會(huì)用到這個(gè)字段瞄桨。
iostat(1)是以/proc/diskstats為基礎(chǔ)計(jì)算出來的,因?yàn)?proc/diskstats并未把隊(duì)列等待時(shí)間和硬盤處理時(shí)間分開讶踪,所以凡是以它為基礎(chǔ)的工具都不可能分別提供disk service time以及與queue有關(guān)的值芯侥。
注:下面的公式中“Δ”表示兩次取樣之間的差值,“Δt”表示采樣周期乳讥。
tps:每秒I/O次數(shù)=[(Δrd_ios+Δwr_ios)/Δt]
r/s:每秒讀操作的次數(shù)=[Δrd_ios/Δt]
w/s:每秒寫操作的次數(shù)=[Δwr_ios/Δt]
rkB/s:每秒讀取的千字節(jié)數(shù)=[Δrd_sectors/Δt]*[512/1024]
wkB/s:每秒寫入的千字節(jié)數(shù)=[Δwr_sectors/Δt]*[512/1024]
rrqm/s:每秒合并讀操作的次數(shù)=[Δrd_merges/Δt]
wrqm/s:每秒合并寫操作的次數(shù)=[Δwr_merges/Δt]
avgrq-sz:每個(gè)I/O的平均扇區(qū)數(shù)=[Δrd_sectors+Δwr_sectors]/[Δrd_ios+Δwr_ios]
avgqu-sz:平均未完成的I/O請(qǐng)求數(shù)量=[Δtime_in_queue/Δt]
(手冊(cè)上說是隊(duì)列里的平均I/O請(qǐng)求數(shù)量柱查,更恰當(dāng)?shù)睦斫鈶?yīng)該是平均未完成的I/O請(qǐng)求數(shù)量。)
await:每個(gè)I/O平均所需的時(shí)間=[Δrd_ticks+Δwr_ticks]/[Δrd_ios+Δwr_ios]
(不僅包括硬盤設(shè)備處理I/O的時(shí)間云石,還包括了在kernel隊(duì)列中等待的時(shí)間唉工。)
r_await:每個(gè)讀操作平均所需的時(shí)間=[Δrd_ticks/Δrd_ios]
不僅包括硬盤設(shè)備讀操作的時(shí)間,還包括了在kernel隊(duì)列中等待的時(shí)間汹忠。
w_await:每個(gè)寫操作平均所需的時(shí)間=[Δwr_ticks/Δwr_ios]
不僅包括硬盤設(shè)備寫操作的時(shí)間淋硝,還包括了在kernel隊(duì)列中等待的時(shí)間雹熬。
%util:該硬盤設(shè)備的繁忙比率=[Δio_ticks/Δt]
表示該設(shè)備有I/O(即非空閑)的時(shí)間比率,不考慮I/O有多少谣膳,只考慮有沒有竿报。
svctm:已被廢棄的指標(biāo),沒什么意義继谚,svctm=[util/tput]
對(duì)iostat(1)的恰當(dāng)解讀有助于正確地分析問題烈菌,我們結(jié)合實(shí)際案例進(jìn)一步討論。
關(guān)于rrqm/s和wrqm/s
前面講過花履,如果兩個(gè)I/O操作發(fā)生在相鄰的數(shù)據(jù)塊時(shí)僧界,它們可以被合并成一個(gè),以提高效率臭挽,合并的操作通常是I/O scheduler(也叫elevator)負(fù)責(zé)的捂襟。
以下案例對(duì)許多硬盤設(shè)備執(zhí)行同樣的壓力測(cè)試,結(jié)果惟有sdb比其它硬盤都更快一些欢峰,可是硬盤型號(hào)都一樣葬荷,為什么sdb的表現(xiàn)不一樣?
可以看到其它硬盤的rrqm/s都為0纽帖,而sdb不是宠漩,就是說發(fā)生了I/O合并,所以效率更高懊直,r/s和rMB/s都更高扒吁,我們知道I/O合并是內(nèi)核的I/O scheduler(elevator)負(fù)責(zé)的,于是檢查了sdb的/sys/block/sdb/queue/scheduler室囊,發(fā)現(xiàn)它與別的硬盤用了不同的I/O scheduler雕崩,所以表現(xiàn)也不一樣。
%util與硬盤設(shè)備飽和度
%util表示該設(shè)備有I/O(即非空閑)的時(shí)間比率融撞,不考慮I/O有多少盼铁,只考慮有沒有。由于現(xiàn)代硬盤設(shè)備都有并行處理多個(gè)I/O請(qǐng)求的能力尝偎,所以%util即使達(dá)到100%也不意味著設(shè)備飽和了饶火。舉個(gè)簡(jiǎn)化的例子:某硬盤處理單個(gè)I/O需要0.1秒,有能力同時(shí)處理10個(gè)I/O請(qǐng)求致扯,那么當(dāng)10個(gè)I/O請(qǐng)求依次順序提交的時(shí)候肤寝,需要1秒才能全部完成,在1秒的采樣周期里%util達(dá)到100%抖僵;而如果10個(gè)I/O請(qǐng)求一次性提交的話鲤看,0.1秒就全部完成,在1秒的采樣周期里%util只有10%裆针∨倌Γ可見,即使%util高達(dá)100%世吨,硬盤也仍然有可能還有余力處理更多的I/O請(qǐng)求澡刹,即沒有達(dá)到飽和狀態(tài)。那么iostat(1)有沒有哪個(gè)指標(biāo)可以衡量硬盤設(shè)備的飽和程度呢耘婚?很遺憾罢浇,沒有。
await多大才算有問題
await是單個(gè)I/O所消耗的時(shí)間沐祷,包括硬盤設(shè)備處理I/O的時(shí)間和I/O請(qǐng)求在kernel隊(duì)列中等待的時(shí)間嚷闭,正常情況下隊(duì)列等待時(shí)間可以忽略不計(jì),姑且把a(bǔ)wait當(dāng)作衡量硬盤速度的指標(biāo)吧赖临,那么多大算是正常呢胞锰?
對(duì)于SSD,從0.0x毫秒到1.x毫秒不等兢榨,具體看產(chǎn)品手冊(cè)嗅榕;
對(duì)于機(jī)械硬盤,可以參考以下文檔中的計(jì)算方法:
http://cseweb.ucsd.edu/classes/wi01/cse102/sol2.pdf
大致來說一萬轉(zhuǎn)的機(jī)械硬盤是8.38毫秒吵聪,包括尋道時(shí)間凌那、旋轉(zhuǎn)延遲、傳輸時(shí)間吟逝。
在實(shí)踐中帽蝶,要根據(jù)應(yīng)用場(chǎng)景來判斷await是否正常,如果I/O模式很隨機(jī)块攒、I/O負(fù)載比較高励稳,會(huì)導(dǎo)致磁頭亂跑,尋道時(shí)間長(zhǎng)囱井,那么相應(yīng)地await要估算得大一些麦锯;如果I/O模式是順序讀寫,只有單一進(jìn)程產(chǎn)生I/O負(fù)載琅绅,那么尋道時(shí)間和旋轉(zhuǎn)延遲都可以忽略不計(jì)扶欣,主要考慮傳輸時(shí)間,相應(yīng)地await就應(yīng)該很小千扶,甚至不到1毫秒料祠。在以下實(shí)例中,await是7.50毫秒澎羞,似乎并不大髓绽,但考慮到這是一個(gè)dd測(cè)試,屬于順序讀操作妆绞,而且只有單一任務(wù)在該硬盤上顺呕,這里的await應(yīng)該不到1毫秒才算正常:
1
2Device:rrqm/swrqm/sr/sw/srsec/swsec/savgrq-szavgqu-szawaitsvctm%util
sdg0.000.00133.000.002128.000.0016.001.007.507.4999.60
對(duì)磁盤陣列來說枫攀,因?yàn)橛杏布彺妫瑢懖僮鞑坏嚷浔P就算完成株茶,所以寫操作的service time大大加快了来涨,如果磁盤陣列的寫操作不在一兩個(gè)毫秒以內(nèi)就算慢的了;讀操作則未必启盛,不在緩存中的數(shù)據(jù)仍然需要讀取物理硬盤蹦掐,單個(gè)小數(shù)據(jù)塊的讀取速度跟單盤差不多。