前幾天微博上有同窗問我磁盤util達到了100%時程序性能降低的問題,因爲信息實在有限,我也沒有辦法幫太大的忙,這篇blog只是想給他列一下在磁盤util很高的時候如何經過blktrace+debugfs找到發生IO的文件,而後再結合本身的應用程序,分析出這些IO究竟是誰產生的,最終目的固然是儘可能減小沒必要要的IO干擾,提升程序的性能。node
blktrace是Jens Axobe寫的一個跟蹤IO請求的工具,Linux系統發起的IO請求均可以經過blktrace捕獲並分析,關於這個工具的介紹請自行google之,這裏推薦咱們部門的褚霸同窗的blog,裏面有好幾篇文章分別介紹了blktrace, blkparse以及blkiomon等工具的使用。ios
debugfs是ext2, ext3, ext4文件系統提供的文件系統訪問工具,經過它咱們能夠不經過mount文件系統而直接訪問文件系統的內容,它是e2fsprogs的一部分,默認應該都是安裝的,詳細的說明能夠經過man debugfs獲得。工具
下面我來演示一下如何經過這兩個工具的配合來找到磁盤IO的源頭。性能
先看一個簡單的例子:
在一個終端會輸入以下命令:
while [ 1 ];do dd if=/dev/zero of=test_file bs=4k count=20 seek=$RANDOM oflag=sync;done
隨機的在test_file裏面寫數據形成較大的IO壓力,如今看看如何經過blktrace和debugfs抓到它。google
1. 經過iostat觀察到有很大的磁盤壓力
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sdb 0.00 2759.00 0.00 3515.50 0.00 50196.00 14.28 0.90 0.26 0.24 85.70debug
2. 咱們看到sdb壓力很大,這時候就須要經過blktrace抓取對應盤的數據
blktrace /dev/sdb 有IO壓力的時候一下子就能夠了,經過ctrl+c中止抓取。
blktrace是須要debugfs支持的,若是系統提示debugfs沒有mount,須要先mount上
mount -t debugfs none /sys/kernel/debug 再執行blktrace命令日誌
3. 將blktrace抓出來的二進制文件轉成文本格式。
blkparse sdb.blktrace.* > 1.logblog
4. 開始分析日誌
grep ‘ A ‘ 1.log|head -n 5生命週期
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
8,16 0 52 0.001361766 2872 A WS 420151 + 8 <- (8,17) 420088
8,16 0 65 0.001440210 2872 A WS 420159 + 8 <- (8,17) 420096
8,16 0 78 0.001518207 2872 A WS 420167 + 8 <- (8,17) 420104
8,16 0 91 0.001596083 2872 A WS 420175 + 8 <- (8,17) 420112get
爲啥要grep ‘ A ‘呢?由於這條信息是上層一個讀寫請求進入到Linux IO協議棧的第一步,只有在這裏咱們能夠看到清晰的請求原始信息。好比
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
這條說明是設備(8,17)也就是sdb1上產生的扇區爲420080的寫請求(讀請求的話會在WS對應的位置出現‘R’),長度是8,它被映射到(8,16)上位置爲420143。這個IO請求的完整生命週期是這樣的:
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
8,16 0 41 0.001244984 2872 G WS 420143 + 8 [dd]
8,16 0 43 0.001246609 2872 I WS 420143 + 8 [dd]
8,16 0 45 0.001255064 2872 D WS 420143 + 8 [dd]
8,16 0 46 0.001325168 0 C WS 420143 + 8 [0]
能夠看到從’ A ‘的下一條開始都是以整個設備的扇區號爲標識的,不方便咱們找到對應的分區。
5. 下面就開始經過debugfs來分析這條讀寫請求的來源了。
(8, 17)是sdb1, 420080是扇區號(IO層的基本單位是扇區sector,大小是512bytes),而文件系統層是經過塊block來管理的,通常的ext3,ext4的塊block大小是4096*,由此可得這個請求對應到文件系統的塊block號是420080/8=52510, debugfs提供了命令icheck能夠經過block號找到它對應的文件的inode。
#debugfs -R ‘icheck 52510′ /dev/sdb1
debugfs 1.43-WIP (1-Aug-2012)
Block Inode number
52510 12
6. 經過inode number找到對應的文件名,很幸運,debugfs又提供了另一條命令ncheck能夠找到inode對應的文件名。
#debugfs -R ‘ncheck 12′ /dev/sdb1
debugfs 1.43-WIP (1-Aug-2012)
Inode Pathname
12 //test_file
你們能夠看到,咱們如今已經成功找到了test_file這個文件啦,至此塊設備層和文件系統層的分析工做已經結束了,下面就能夠結合應用看看爲啥會對這個文件有如此頻繁的讀寫操做了!
*塊大小實際上也可以經過debugfs來獲得。debugfs -R ‘stats’ /dev/sdb1|grep 「Block size」