如果我們想知道,在一段時(shí)間內(nèi),那一個(gè)磁盤塊被讀寫的頻率最高,怎么辦?我問這個(gè)問題是看到taobao kernel wiki上面有這么一段話,看了我十分心癢:
通過對(duì)blktrace的輸出結(jié)果進(jìn)行分析,我們可以對(duì)特定時(shí)間段內(nèi)發(fā)生的讀、寫操作的磁盤塊進(jìn)行I/O頻次統(tǒng)計(jì)。結(jié)合通過將磁盤塊I/O頻度統(tǒng)計(jì)和page cache命中率統(tǒng)計(jì)相結(jié)合,就可以比較有效的判斷服務(wù)器節(jié)點(diǎn)的cache使用效率。通過這套工具,CDN系統(tǒng)修正了一個(gè)固態(tài)硬盤上cache管理的缺陷,顯著提高了I/O性能(詳細(xì)信息)淘寶大神給了一個(gè)shell腳本解決這個(gè)問題,但是我守著代碼,不知道怎么用。就研究了下blktrace和大神的代碼。常常聽淘寶的霸爺,提起blktrace。iostat,iotop這些的工具也是統(tǒng)計(jì)磁盤IO的,也非常有用,但是和blktrace比,信息過于summarized,而blktrace跟蹤了發(fā)生在塊設(shè)備層的很多事件,簡直就是整個(gè)塊設(shè)備層事件的回放。blktrace能夠trace那些事件呢?
上面這個(gè)膠片來自HP的介紹blktrace的膠片,介紹的非常好,是參考文獻(xiàn)中一篇。 這些事件都會(huì)被blktrace 捕捉到。由于這些事件要和kernel代碼中block device的work flow一一對(duì)應(yīng),目前我的功力尚不足,所以我就不一一介紹這些事件了。 blktrace輸出的東西,不是文本,是一些特殊的格式,要想可讀,需要blkparse解析blktrace的輸出。 我們看下blktrace和blkparse合作方式
這是一個(gè)比較典型的使用: blktrace -d表示monitor哪個(gè)設(shè)備,-o -表示講輸出吐出到標(biāo)準(zhǔn)輸出。 blkparse -i - 表示從標(biāo)準(zhǔn)輸入獲取信息,-o 表示講解析的內(nèi)容記錄在blkparse.out 我們看下輸出長的什么樣子:
這個(gè)膠片非常好的介紹了各個(gè)字段的含義。主次設(shè)備號(hào),CPU ID,sequence num,time stamp PID ,起始扇區(qū)號(hào),進(jìn)程名字比較好理解,比較難理解的是$6,$7$6中的GPQMDC,一堆字母,代表什么含義?$7的WR 又代表什么含義呢? 一個(gè)一個(gè)來,對(duì)于$6,表示的是event,官方手冊(cè)給了事件對(duì)應(yīng)表:
那么$7是干嘛的呢? 基本上是R和W,也會(huì)出現(xiàn)B和S. R表示是read操作,W表示write操作,B是barrier operation,S是synchronous operation。 看到這個(gè)blkparse的輸出,我們發(fā)現(xiàn)這些更像是raw data,需要我們挖掘背后的信息。btt這個(gè)工具就是一個(gè)分析輸出得到更高層信息的tool,他不是我們本文的重點(diǎn),我們不提他。 回到開篇的問題,如何知道which磁盤扇區(qū)被讀寫的次數(shù)最多?有了blkparse的輸出,我們完全可以做到這個(gè)統(tǒng)計(jì):淘寶的Coly大神的shell腳本已經(jīng)幫我們作了這個(gè)事情。
root@manu-hacks:~/code/shell/blkstrace_calculator# cat cal.sh
#!/bin/bash
TMP_DIR=".blktrace_cal"
# extend the blktracelogto"blockid R/W"
extend()
{
awk-v max=$2-vmod=$3'{
if(NR%max==mod&&$6=="D"&&(index($7,"R")||index($7,"W"))){
for(i=0;i<$10;?i++)?{
print $8+i" "substr($7,1,1);
}
}
}'$1|sort-k1-nr>$TMP_DIR/.tmp.$1.$3
touch $TMP_DIR/$3.ok
}
usage()
{
echo"Usage: $1 input_log [parallel_num]"
exit
}
rm-rf $TMP_DIR
mkdir $TMP_DIR
if["$1"==""];then
usage $0
fi
# does input_log exists?
if[!-f $1];then
echo"($1) not exists"
exit
fi
parallel=$2
if["$2"==""];then
parallel=4
fi
echo"[input: $1]"
max=`expr $parallel-1`
files=""
filename=`basename $1`
echo"[run $parallel process]"
foriin`seq 0 $max`
do
extend $filename $parallel $i&
files=$files" $TMP_DIR/.tmp.$filename.$i"
done
echo"processing...."
nr=0
# awk will finishifall*.ok created.
while[$nr-ne"$parallel"]
do
nr=`find $TMP_DIR-maxdepth 1-name"*.ok"|wc-l`
echo-n"."
sleep 1
done
echo""
echo"merge sort"
sort-m-k1-nr $files|uniq-c|sort-k1-nr>tmp
total=`awk'{sum+=$1}END{print sum}'tmp`
awk-v sum=$total'{
print $0"\t"$1*1000/sum;
}'tmp>result
echo"sort finish."
rm-rf $TMP_DIR
這段代碼是Coly大神的代碼,我無意抄襲前輩,只是晚輩拿來欣賞學(xué)習(xí),光榮屬于淘寶的Coly前輩。 先說parallel,這個(gè)是為了充分利用CPU資源,讓多個(gè)CPU一起來執(zhí)行extend。NR%max==mod將一個(gè)文件按照行分開,由多個(gè)進(jìn)程分別處理之。不多講。 extend的含義也比較簡單:
20397704是起始扇區(qū),+ 8表示的連續(xù)8個(gè)扇區(qū)都在本次事件之內(nèi),也就是說20397704/20397705/20397706..都是本次事件涉及的扇區(qū)。 OK,我們看下cal.sh的使用及輸出:
當(dāng)前目錄下生成了tmp和result文件:
我們可以看到,扇區(qū)號(hào)為454375583被訪問的次數(shù)為39次,占總訪問的千分之0.228744。那這個(gè)扇區(qū)屬于拿個(gè)文件呢?debugfs就可以來幫忙了.我們以訪問27次的264753359扇區(qū)為例。扇區(qū)是512字節(jié),我的文件系統(tǒng)ext4的塊大小是4K,所以根據(jù)扇區(qū)可以定位的塊號(hào),debugfs根據(jù)塊號(hào),可以定位到inode,再根據(jù)inode,就可定位到filename。
我們發(fā)現(xiàn),這個(gè)文件被讀寫的次數(shù)最多。誰干的? lsof來幫忙?
我們用Coly大神的腳本和blktrace/blkparse就解決了磁盤塊IO訪問頻率的統(tǒng)計(jì)。如果有個(gè)別的block被頻繁的讀取,表示cache的替換效率不高。
-
磁盤
+關(guān)注
關(guān)注
1文章
375瀏覽量
25201 -
固態(tài)硬盤
+關(guān)注
關(guān)注
12文章
1459瀏覽量
57336
原文標(biāo)題:使用blktrace統(tǒng)計(jì)磁盤塊I/O訪問頻率
文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論