性能分析之IO分析-從IO高到具體文件

IO的性能分析一直是性能分析的重點之一,分析的思路是:

在代碼的邏輯清晰的狀況下,是徹底能夠知道哪些文件是頻繁讀寫的。可是對性能分析人員來講,一般是面對一個不是本身編寫的系統,有時仍是多個團隊合做產生的系統。這時就會出現不少的推諉和爭執。若是能夠迅速地把問題到一個段具體的代碼,到一個具體的文件,那就能夠提升溝通的效率。node

一般狀況在linux 環境下,經過 vmstat 或者 iostat 命令能夠發現磁盤IO的異常,能夠看到系統級的磁盤讀寫量及CPU佔用率,但沒法明肯定位到是什麼進程在做祟,安裝iotop 後,能夠定位到進程,但並不知道改進程在操做什麼文件。

本文是考慮從系統級的工具來完成這個操做,比較具備通用性。在這以前須要先理解一下文件的一個重要的屬性:inode。什麼是inode呢?先來看一個示意圖:

磁盤上最小的存儲單元是扇區sector,每8個扇區組成一個塊block(4096字節)。以下所示:
[root@7DGroup2 ~]# tune2fs -l /dev/vda1|grep Block
Block count: 10485504
Block size: 4096
Blocks per group: 32768
[root@7DGroup2 ~]#
文件的存儲就是由這些 塊組成的,當塊多了以後就成了以下這樣(其實磁盤上的塊比這個圖中多得多,這裏只是示意圖):

其中紅色的這部分是存儲的文件,咱們一般在文件系統中直接ls或者用其餘命令操做文件的時候是根據路徑來操做的,那些是上層的命令。當咱們執行了一個命令以後,操做系統會來找到這些文件作相應的操做,怎麼找到這些文件呢,那就須要inode了。Inode用來存儲這些文件的元信息,也就是索引節點,它包括的信息有:
· 字節數
· User ID
· Group ID
· 讀、寫、執行權限
· 時間戳,共有三個:ctime指inode上一次變更的時間,mtime指文件內容上一次變更的時間,atime指文件上一次打開的時間
· 連接數,有多少文件名指向這個inode
· 文件數據block的位置
經過這些信息,咱們才能實現對文件的操做。這個inode其實也是存儲在磁盤上的,也須要佔用一些空間,如上圖中的綠色部分所示。
當咱們在系統級看到IO太高的時候,好比下圖所示:

從上圖能夠看到,這系統幾乎全部的CPU都在等IO。這時怎麼辦?就用咱們前面提到的分析的思路,查看進程級和線程級的IO,進而找到具體的文件。下面咱們來具體實現。
這裏咱們用的是systemtap,這個工具7Dgroup以前的文章中提到的,但沒有展開說。後面若是有可能咱們再多寫些相似的工具原理和使用方法。
Systemtap的邏輯圖以下:

從邏輯圖上看,它工做在內核層面,不是shell的層面。
SystemTap爲咱們開啓了一扇通往系統內核的大門,SystemTap 自帶的examples中提供一些磁盤IO相關的監控例子。
以 iotop.stp 爲例,源碼以下:linux

#!/usr/bin/stap

global reads, writes, total_io

probe vfs.read.return {
reads[execname()] +=  bytes_read
}

probe vfs.write.return {
writes[execname()] +=  bytes_written
}

# print top 10 IO processes every 5 seconds
probe timer.s(5) {
foreach (name in writes)
    total_io[name] +=  writes[name]
foreach (name in reads)
    total_io[name] +=  reads[name]
printf ("%16s\t%10s\t%10s\n",  "Process", "KB Read", "KB Written")
foreach (name in total_io-  limit 10)
     printf("%16s\t%10d\t%10d\n", name,
            reads[name]/1024, writes[name]/1024)
delete reads
delete writes
delete total_io
print("\n")
}

執行的結果是:每隔5秒打印讀寫總量排前10位的進程。

該腳本有兩個問題:
按照進程名字統計,存在統計偏差,進程名一致,但PID不同的進程,都統計到一塊兒;
咱們依然不能知道進程操做了什麼文件。
經過對probe點的分析(sudo stap -L'vfs.{write,read}'),咱們能夠知道,vfs.read,vfs.write有局部變量 ino 能夠利用,ino 是文件的inode,這樣咱們就能夠明確的探測到讀寫量最多的進程及文件。
$ sudo stap -L 'vfs.{write,read}'
vfs.read file:long pos:long buf:long bytes_to_read:long dev:long devname:string ino:long name:string argstr:string $file:struct file* $buf:char $count:size_t $pos:loff_t
vfs.write file:long pos:long buf:long bytes_to_write:long dev:long devname:string ino:long name:string argstr:string $file:struct file* $buf:char const $count:size_t $pos:loff_t
擴展過的腳本以下:ios

#!/usr/bin/stap

global reads, writes, total_io

probe vfs.read.return {
 reads[execname(),pid(),ino] += bytes_read
}

probe vfs.write.return {
 writes[execname(),pid(),ino] += bytes_written
}

# print top 10 IO processes every 5 seconds
probe timer.s(5) {
foreach  ([name,process,inode] in writes)
     total_io[name,process,inode] += writes[name,process,inode]
foreach ([name,process,inode] in reads)
     total_io[name,process,inode] += reads[name,process,inode]
printf  ("%16s\t%8s\t%8s\t%10s\t%10s\n", "Process",  "PID", "inode", "KB Read", "KB  Written")
foreach  ([name,process,inode] in total_io- limit 10)
     printf("%16s\t%8d\t%8d\t%10d\t%10d\n", name,process,inode,
            reads[name,process,inode]/1024, writes[name,process,inode]/1024)
delete reads
delete writes
delete total_io
print("\n")

}
咱們來作個實驗,執行dd命令來作一個高磁盤讀寫操做。
執行命令以下:
dd bs=64k count=4k if=/dev/zero of=test oflag=dsync
這條命令執行的效果是:dd在執行時每次都會進行同步寫入操做,每次從/dev/zero 讀取64k數據,而後寫入當前目錄下的test文件,一共重複4K次。在linux系統中, /dev/zero 是一個特殊的文件,當你讀它的時候,它會提供無限的空字符(NULL, ASCII NUL, 0x00)。
iotop.stp監控結果以下:

經過監控,咱們知道了,PID 爲 2978 的 dd 進程 讀取 inode 爲1047的文件,寫入inode爲 663624的文件,這兩個是讀寫最多的操做。
一般狀況下,咱們並不知道inode對應文件的位置,能夠經過 find / -inum 1047 找到對應的文件。
經過stat 命令,咱們能夠看到文件inode詳細的描述。
$ stat /dev/zero
文件:"/dev/zero"
大小:0 塊:0 IO 塊:4096 字符特殊文件
設備:5h/5d Inode:1047 硬連接:1 設備類型:1,5
權限:(0666/crw-rw-rw-) Uid:( 0/ root) Gid:( 0/ root)
環境:system_u:object_r:zero_device_t:s0
最近訪問:2017-05-02 10:50:03.242425632 +0800
最近更改:2017-05-02 10:50:03.242425632 +0800
最近改動:2017-05-02 10:50:03.242425632 +0800
建立時間:-shell

這個分析思路在任何一個系統中均可以說是能用的,只是不一樣的系統用的工具不一樣。此次用的環境是CentOS,那在其餘的系統中,只能找到相對應的其餘工具了。工具

再次強調,瞭解原理、理清思路是性能分析的重點。工具的使用是爲了驗證思路的正確性。千萬不要捨本逐末。性能

相關文章
相關標籤/搜索