利用blktrace分析磁盘I/O
原文:https://blog.csdn.net/ygtlovezf/article/details/80528300
blktrace对于分析block I/O是个非常好的工具,本篇文章记录了如何使用blktrace。
blktrace原理
blktrace是对通用块层(block layer)的I/O跟踪机制,它能抓取详细的I/O请求(request),发送到用户空间。
blktrace主要由3部分组成:
内核部分
- 记录内核到用户空间的I/O追踪信息的程序
- 分析、展示I/O追踪信息的程序
- 主要在block layer实现,抓取的数据通过debugfs来传递。每个被跟踪的设备都有一个在debugfs挂载目录的文件。debugfs挂载目录默认是:/sys/kernel/debug
用官方的一张图来直观的展现:
一个I/O请求进入block layer之后,可能会经历下面的过程:
- Remap: 可能被DM(Device Mapper)或MD(Multiple Device, Software RAID) remap到其它设备
- Split: 可能会因为I/O请求与扇区边界未对齐、或者size太大而被分拆(split)成多个物理I/O
- Merge: 可能会因为与其它I/O请求的物理位置相邻而合并(merge)成一个I/O
- 被I/O Scheduler依照调度策略发送给driver
- 被driver提交给硬件,经过HBA、电缆(光纤、网线等)、交换机(SAN或网络)、最后到达存储设备,设备完成I/O请求之后再把结果发回。
blktrace使用
- 安装blktrace包
yum install blktrace
- 追踪指定设备的I/O
[root@k8s-slave9 longterm_io] # blktrace -d /dev/sde ^C=== sde ===CPU 0: 38 events, 2 KiB dataCPU 1: 1 events, 1 KiB dataCPU 2: 232 events, 11 KiB dataCPU 3: 2 events, 1 KiB dataCPU 4: 41 events, 2 KiB data...Total: 567 events (dropped 0), 27 KiB data
-d 指定具体的设备名
上面是抓取一段时间后,Ctrl+C中止的。也可以指定时间:-w
blktrace执行完之后,会生产很多文件,每个CPU都会有一个文件,文件名组成:<设备名>.blktrace.,如下:
[root@k8s-slave9 longterm_io]ls
sde.blktrace.0 sde.blktrace.12 sde.blktrace.16 sde.blktrace.2 sde.blktrace.23 sde.blktrace.27 sde.blktrace.30 sde.blktrace.34 sde.blktrace.38 sde.blktrace.6
...
抓取IO信息,完成了第一步,我们要分析这些I/O,就需要下面的工具。
blkparse分析数据
解析IO追踪信息
blkparse是一个会把不同CPU的I/O trace文件合并,并解析、格式化输出为对用户可读友好IO信息的工具。
先把上面生成的所有CPU I/O trace文件合并成一个文件:
[root@k8s-slave9 longterm_io] # blkparse -i sde -d sde.blktrace.bin Input file sde.blktrace.0 added Input file sde.blktrace.1 added Input file sde.blktrace.2 added Input file sde.blktrace.3 added Input file sde.blktrace.4 added ... -----------------------------第一个IO开始8,64 35 1 0.000000000 28378 A W 470236984 + 40 <- (8,65) 470234936 8,64 35 2 0.000000670 28378 Q W 470236984 + 40 [kworker /u82 :1] 8,64 35 3 0.000005125 28378 G W 470236984 + 40 [kworker /u82 :1] 8,64 35 4 0.000005443 28378 P N [kworker /u82 :1] 8,64 35 5 0.000009123 28378 I W 470236984 + 40 [kworker /u82 :1] 8,64 35 6 0.000009978 28378 U N [kworker /u82 :1] 1 8,64 35 7 0.000010638 28378 D W 470236984 + 40 [kworker /u82 :1] 8,64 31 1 0.207382887 0 C W 470236984 + 40 [0] -----------------------------第一个IO完成 -----------------------------第二个IO开始8,64 2 1 10.239998442 4861 A FWFSM 469242512 + 2 <- (8,65) 469240464 8,64 2 2 10.239999862 4861 Q FWFSM 469242512 + 2 [kworker /2 :0H] 8,64 2 3 10.240004505 4861 G FWFSM 469242512 + 2 [kworker /2 :0H] 8,64 2 4 10.240005325 4861 P N [kworker /2 :0H] 8,64 2 5 10.240007109 4861 I FWFSM 469242512 + 2 [kworker /2 :0H] 8,64 2 6 10.240008795 4861 U N [kworker /2 :0H] 1 8,64 4 1 10.482792539 0 D WFSM 469242512 + 2 [swapper /0 ] 8,64 8 1 10.492646670 0 C WFSM 469242512 + 2 [0] -----------------------------第二个IO完成 ... CPU0 (sde): Reads Queued: 1, 8KiB Writes Queued: 3, 172KiB Read Dispatches: 1, 8KiB Write Dispatches: 3, 172KiB Reads Requeued: 0 Writes Requeued: 0 Reads Completed: 1, 8KiB Writes Completed: 3, 172KiB Read Merges: 0, 0KiB Write Merges: 0, 0KiB Read depth: 1 Write depth: 4 IO unplugs: 4 Timer unplugs: 0 ... Total (sde): Reads Queued: 23, 184KiB Writes Queued: 41, 652KiB Read Dispatches: 23, 184KiB Write Dispatches: 36, 653KiB Reads Requeued: 0 Writes Requeued: 0 Reads Completed: 23, 184KiB Writes Completed: 53, 653KiB Read Merges: 0, 0KiB Write Merges: 5, 91KiB IO unplugs: 57 Timer unplugs: 0 Throughput (R /W ): 0KiB /s / 1KiB /s Events (sde): 500 entries Skips: 0 forward (0 - 0.0%)
中间那段I/O处理阶段说明:
第一列:设备号 主设备号,次设备号
第二列:CPU
第三列:顺序号
第五列:时间戳
第六列:PID 进程号
第七列:具体事件
第八列:具体的读写操作
W:WriteR:ReadS:SyncFWF:第一个F是Flush,W还是Write,第二个F是FUA(force unit acess)M:MetadataD:DiscardB:Barrier从抓取的I/O来看,所有I2D耗时比较长的都是FWFSM的操作。
第九列:磁盘起始块+操作的块的数量
第十列:进程名或具体的命令
通过这些输出,我们就可以明确看到,每个阶段的具体耗时,就可以定位I/O慢在哪个阶段,也是需要深入的分析什么原因导致的。
具体动作(或事件)的字母代表意义:
- A remap 对于栈式设备,进来的I/O将被重新映射到I/O栈中的具体设备
- X split 对于做了Raid或进行了device mapper(dm)的设备,进来的IO可能需要切割,然后发送给不同的设备
- Q queued I/O进入block layer,将要被request代码处理(即将生成IO请求)
- G get request I/O请求(request)生成,为I/O分配一个request 结构体。
- M back merge 之前已经存在的I/O request的终止block号,和该I/O的起始block号一致,就会合并。也就是向后合并
- F front merge 之前已经存在的I/O request的起始block号,和该I/O的终止block号一致,就会合并。也就是向前合并
- I inserted I/O请求被插入到I/O scheduler队列
- S sleep 没有可用的request结构体,也就是I/O满了,只能等待有request结构体完成释放
- P plug 当一个I/O入队一个空队列时,Linux会锁住这个队列,不处理该I/O,这样做是为了等待一会,看有没有新的I/O进来,可以合并
- U unplug 当队列中已经有I/O request时,会放开这个队列,准备向磁盘驱动发送该I/O。
这个动作的触发条件是:超时(plug的时候,会设置超时时间);或者是有一些I/O在队列中(多于1个I/O) - D issued I/O将会被传送给磁盘驱动程序处理
- C complete I/O处理被磁盘处理完成。
btt分析数据
blkparse只是将blktrace数据转成可以人工阅读的格式,由于数据量通常很大,人工分析并不轻松。btt是对blktrace数据进行自动分析的工具。
使用btt解析数据,查看I/O的整体情况
[root@k8s-slave9 longterm_io] # btt -i sde.blktrace.bin ==================== All Devices ====================ALL MIN AVG MAX N --------------- ------------- ------------- ------------- -----------Q2Q 0.000002013 7.354920889 30.208019079 63 Q2G 0.000000889 0.000003898 0.000016826 59 G2I 0.000000591 0.000003383 0.000035937 59 Q2M 0.000000333 0.000001295 0.000002440 5 I2D 0.000000503 0.065649284 0.252996244 59 M2D 0.000003840 0.000011816 0.000017717 5 D2C 0.000128883 0.056202494 0.254664063 64 Q2C 0.000131324 0.116730664 0.262633229 64==================== Device Overhead ====================DEV | Q2G G2I Q2M I2D D2C ---------- | --------- --------- --------- --------- ---------( 8, 64) | 0.0031% 0.0027% 0.0001% 51.8462% 48.1472% ---------- | --------- --------- --------- --------- ---------Overall | 0.0031% 0.0027% 0.0001% 51.8462% 48.1472%==================== Device Merge Information ====================DEV | #Q #D Ratio | BLKmin BLKavg BLKmax Total ---------- | -------- -------- ------- | -------- -------- -------- --------( 8, 64) | 64 59 1.1 | 2 28 176 1675 ...
第一个表的第一列是具体的I/O阶段,第二、三、四列分别是最小耗时、平均耗时、最大耗时(单位:s),第五列是I/O数。
第二个表是对第一个表做了耗时统计,看看整个I/O阶段,哪个阶段耗时占用最多。
第三个表是进行合并的信息,但是从内容来看,没有merge信息啊。后面有所有I/O中操作的块数量的最小值、平均值、最大值。
IO处理阶段:
Q2Q: 相邻两次进入通用块层的I/O间隔
Q2G:I/O进入block layer到I/O请求(request)生成的时间
G2I :I/O请求生成到被插入I/O请求队列(request queue)的时间
Q2M:I/O进入block层到该I/O被和已存在的I/O请求合并的时间
I2D :I/O请求进入request queue队到分发到设备驱动的时间
M2D:I/O合并成I/O请求到分发到设备驱动的时间
D2C:I/O分到到设备驱动到设备处理完成时间
在上述过程中,Q2M、M2D两个阶段不是必然发生的,只有可以merge的I/O才会进行合并。
生产不同维度的报告
查看所有I/O D2C阶段的具体延时: (-l参数将会分析D2C阶段延迟,该参数后是具体的输出文件名)
[root@k8s-slave9 longterm_io] # btt -i sde.blktrace.bin -l sde.d2c_latency ==================== All Devices ====================ALL MIN AVG MAX N --------------- ------------- ------------- ------------- -----------Q2Q 0.000002013 7.354920889 30.208019079 63 Q2G 0.000000889 0.000003898 0.000016826 59 G2I 0.000000591 0.000003383 0.000035937 59 Q2M 0.000000333 0.000001295 0.000002440 5 I2D 0.000000503 0.065649284 0.252996244 59 M2D 0.000003840 0.000011816 0.000017717 5 D2C 0.000128883 0.056202494 0.254664063 64 Q2C 0.000131324 0.116730664 0.262633229 64 ...
执行完上面的命令后,会有如下文件生成:
[root@k8s-slave9 longterm_io] # ls *.dat 8,64_iops_fp.dat 8,64_mbps_fp.dat sde.d2c_latency_8,64_d2c.dat sys_iops_fp.dat sys_mbps_fp.dat
如上输出,可以看到:有这段时间的IOPS统计(8,64_iops_fp.dat、sys_iops_fp.dat)、带宽统计(8,64_mbps_fp.dat、sys_mbps_fp.dat)、延迟统计(sde.d2c_latency_8,64_d2c.dat)
我们看看这些文件:每个时间点的I /O 个数: [root@k8s-slave9 longterm_io] # cat sys_iops_fp.dat 0 1 10 1 31 1 40 1 44 1 66 1 70 1 100 5 ...每个时间点的带宽: [root@k8s-slave9 longterm_io] # cat sys_mbps_fp.dat 0 0.019531 10 0.000977 31 0.031250 40 0.000977 44 0.003906 66 0.015625 70 0.002441 100 0.048828 ...每个时间点的D2C阶段延迟: [root@k8s-slave9 longterm_io] # cat sde.d2c_latency_8,64_d2c.dat 0.207383 0.207372 10.492647 0.009854 31.439889 0.207854 40.700689 0.009720 44.381372 0.206810 44.381372 0.206810 66.564038 0.004049 70.907380 0.008502 100.047822 0.207767 ...
其中,第一列是时间戳,第二列是具体的内容
查看所有I/O的size、offset等信息:(-B参数将会输出具体的block号,包括起始block、终止block)
[root@k8s-slave9 longterm_io] # btt -i sde.blktrace.bin -B sde.offset ==================== All Devices ====================ALL MIN AVG MAX N --------------- ------------- ------------- ------------- -----------Q2Q 0.000002013 7.354920889 30.208019079 63 Q2G 0.000000889 0.000003898 0.000016826 59 G2I 0.000000591 0.000003383 0.000035937 59 Q2M 0.000000333 0.000001295 0.000002440 5 I2D 0.000000503 0.065649284 0.252996244 59 M2D 0.000003840 0.000011816 0.000017717 5 D2C 0.000128883 0.056202494 0.254664063 64 Q2C 0.000131324 0.116730664 0.262633229 64 ...
上述命令将输出如下的文件:
[root@k8s-slave9 longterm_io] # ls | grep offset sde.offset_8,64_c.dat sde.offset_8,64_r.dat sde.offset_8,64_w.dat xxx_r.dat:读操作相关信息 xxx_w.dat:写操作相关信息xxx_c.dat:所有操作,读写都有
我们看看写操作:
[root@k8s-slave9 longterm_io] # cat sde.offset_8,64_w.dat0.000010638 470236984 47023702410.482792539 469242512 46924251431.232035019 470237016 47023708040.690968712 469242514 46924251644.174561925 703299792 70329980066.559989117 470237072 47023710470.898878399 469242516 46924252199.840054977 470237096 470237152100.864256898 703277841 703277843...
其中第一列是时间戳,第二列是I/O操作的起始block号,第三列是I/O操作的终止block号。
参考
https://www.mimuw.edu.pl/~lichota/09-10/Optymalizacja-open-source/Materialy/10 - Dysk/gelato_ICE06apr_blktrace_brunelle_hp.pdf
http://fibrevillage.com/storage/539-blktrace-and-btt-example-to-debug-and-tune-disk-i-o-on-linux
相关文章:

shiro 同时实现url和按钮的拦截_一个“保存”按钮同时存在“增删改”三种操作,该如何去实现?...
一般情况下,对表格中的数据进行“增删改”操作,都是直接操作数据库。现在有些项目因为设计或者优化的缘故,不对表格中的数据进行“增删改”,而是通过最后“保存”按钮的操作,一次性将数据传至服务器,由服务…

在网络通讯中,如何自己分配可用的端口号和获取自己的ip地址
在编写一些程序时,为了程序可以在其他电脑上也可以使用,而不用手动去更改ip,或者碰到端口不可用的情况。在这里找到了一个好的方法,实际使用也没有问题!故此推荐给大家! 方案: 在构建网络时,使用࿱…

【翻译】ASP.NET WEB API异常处理
当一个web api抛出一个异常后 此异常会被转化成一个HTTP响应 错误代码为500的服务错误 但是如果你不想让客户端看到500的错误码 你也可以自定义错误码 如下代码当用户输入的ID没有与之相关的数据 则返回了错误码为404的错误 (页面未找到) public Product…

hook NtTerminateProcess进行应用的保护
这段时间在学习驱动,然后看到hook ssdt的代码,找了一个写的清晰的学习了一下:http://www.netfairy.net/?post218 这里是hook NtOpenProcess,但是想自己练手所以hook NtTerminateProcess,经过多次蓝屏后,然…

linux系统 长久记录所有用户所有操作记录
在linux系统中想要记录所有登录过当前系统的用户操作,排查有人对当前系统做的何种操作导致系统问题,可以按照如下方法进行。 前言 在描述操作步骤之前,先说一下系统环境变量的相关配置文件 ~/.bashrc和~/.bash_file,这两个文件…

jquery图片播放切换插件
点击这里查看效果可自定义数字样式和左右点击按钮这个更好:移入按钮切换版本更多图片轮播以下是HTML文件代码: 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transiti…

安卓饼状图设置软件_话单及银行卡交易智能分析软件
一、产品概况: 思迈奥SMILE数据智能分析软件是由我司自主设计与研发的一款结合在公安和检察院的侦查业务经验而定制研发的数据智能分析系统,包含于话单、电子银行账单、及其它数据(个人出行数据、社会资源数据、微信数据及其它聊天数据)等的数据导入、检…

跨区域MPLS TE
拓扑: R1配置: mpls label range 100 199 mpls traffic-eng tunnels interface Loopback0 ip address 192.168.1.1 255.255.255.255 ! interface Tunnel1 ip unnumbered Loopback0 tunnel mode mpls traffic-eng tunnel destination 192.168.1.4 tunnel …

C++智能指针: shared_ptr 实现详解
文章目录shared_ptr描述声明作用原理实现函数使用关于shared_ptr循环引用问题shared_ptr描述 声明 shared_ptr属于C11特性中新加的一种智能指针,它的实现方式是模版类,头文件<memory> template <class T> class shared_ptr 所以使用shared…

linux文本处理常用命令
linux文本处理常用命令 linux文本处理命令:grep、sed、printf、awk 1.grep grep的作用是按行查找字符,输出包含字符的行。 #从文件查询 grep hello filename.txt #从管道的输入查询 cat filename.txt|grep hello grep使用示例: grep的查找主要…

arduino 控制无刷电机_智能控制轮椅来了,残疾人的福音!
传统的轮椅已被证明是非常宝贵的工具,为残疾人提供了很多便利,但其只能限制坐在一个位置。外国的一个研究团队通过开发一个功能强大的多功能轮椅,使用户能够通过手机应用程序轻松地在各种各样的位置之间进行切换。(图片来自 IC photo)这是一种…

python科学计算整理
网站: http://bokeh.pydata.org/gallery.html 转载于:https://www.cnblogs.com/gogly/p/3453341.html
TP-link 841N 刷DD-WRT固件
2012年4月20号 今天,笔者逛“太平洋”的时候,发现了一个关于TP-Link 840N刷DD-WRT的帖子,进去逛了一会,突然记得自己家中的那个路由好像也是这个型号的,二话不说,果断收录这条资料,并把所需要的…

网格的铺设问题——骨牌
Problem Description 有一个大小是 2 x n 的网格,现在需要用2种规格的骨牌铺满,骨牌规格分别是 2 x 1 和 2 x 2,请计算一共有多少种铺设的方法。 Input 输入的第一行包含一个正整数T(T<20),表示一共有 T…

C++智能指针:weak_ptr实现详解
文章目录weak_ptr描述声明作用原理实现函数成员使用总结weak_ptr描述 声明 头文件:<memory> 模版类:template <class T> class weak_ptr 声明方式:std::weak_ptr<type_id> statement 作用 根据boost库的官方描述&#…

在PHP中使用全局变量的几种方法
简介即使开发一个新的大型PHP程序,你也不可避免的要使用到全局数据,因为有些数据是需要用到你的代码的不同部分的。一些常见的全局数据有:程序设定类、数据库连接类、用户资料等等。有很多方法能够使这些数据成为全局数据,其中最常…

python处在哪个阶段_python 基础复习
1、简述cpu、内存、硬盘的作用cpu(1)cpu:处理逻辑运算、算术运算(2)cpu:接受指令传给电脑硬件,让其运行内存:(1)内存:从硬盘中读取数据,供其cpu调取指令运行,短暂的存贮数据;运行速度…

android用户界面之WebView教程实例汇总
一、WebView教程1.Android---UI篇---WebView(网络视图)http://www.apkbus.com/android-14259-1-1.html2.webview学习记录http://www.apkbus.com/android-44567-1-1.html3.Android中使用WebView, WebChromeClient和WebViewClient加载网页http://www.apkbu…

java下输出中文的一点研究
网上或者大部分书上都说Java中输出中文使用FileReader类就可以了,但是当你读取一个中文文档时,你会发现,除了乱码,还是乱码。究其原因,这其实是文件流读取时使用的编码方式和文件本身编码方式不同,造成读取出来文件乱码…

C++智能指针:unique_ptr详解
文章目录unique_ptr描述声明作用函数指针描述总结unique_ptr描述 声明 头文件:<memory> 模版类: 默认类型template <class T, class D default_delete<T>> class unique_ptr数组类型template <class T, class D> class uniq…

川崎机器人示教盒维修_专业维修丹阳市KUKA库卡KRC2库卡C4主板维修{苏州罗韦维修}...
发那科机器人故障分析 发那科伺服放大器上LED指示灯故障维修大全_发那科机器人维修,FANUC机器人保养,伺服电机示教器减速器维修,驱动器维修,苏州发那科机器人维修,本文主要介绍了发那科伺服放大器上因故障而出现的各种…

js 文本反向排列显示
一次面试遇到这样的题目 反向输出“how are you” 解决方法 <script language"JavaScript">var message1"how are you";var message2"";for (countmessage1.length; count > 0; count--)message2message1.substring(count,count-1);doc…

2012年12月4期手机网页开发
最近主要做手机上页面的开发,主要框架是,手机安装客户端,加载主站手机应用页面,手机客户端配合主站功能实现本地扫描或重力感应的效果。 针对安卓系统,在开发和调试时发现如下问题:1路径错误&#…

zabbix4.0构建实录
【Nginx】 #wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo [rootcentos ~]# yum -y install zlib pcre pcre-devel openssl openssl-devel[rootcentos ~]# useradd -s /sbin/nologin nginx [rootzabbix-server ~]# yum install -y nginx 【M…

ceph-kvstore-tool 工具使用详解
文章目录简介使用总结简介 ceph-kvstore-tool工具是用来获取存放在leveldb或者rocksdb数据库中的键值元数据。并且该工具能够对kvstore中的数据进行配置,就像是对离线后的osd操作osd map一样 使用该工具,需要安装ceph-test-12.2.1.06-0.el7.centos.x86_…

springboot 订单重复提交_Spring Boot (一) 校验表单重复提交
一、前言在某些情况下,由于网速慢,用户操作有误(连续点击两下提交按钮),页面卡顿等原因,可能会出现表单数据重复提交造成数据库保存多条重复数据。存在如上问题可以交给前端解决,判断多长时间内不能再次点击保存按钮&a…

智能会议白板系统每日开发记录
智能会议白板系统,在开发过程中,整个项目期限内,每月,每周,每天要做的事情,作为组长的记录,多有不足之处,望指点。 转载于:https://www.cnblogs.com/mayijun/p/3458039.html

java.lang.OutOfMemoryError: PermGen space及其解决方法
PermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决方法也一定是加大内存。说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入Per…

ceph-dencoder工具使用详解
文章目录简介使用decode命令用法encode简介 ceph-dencoder工具是一个序列化编码、解码并且打印ceph数据结构的工具。它主要用来调试和测试ceph不同版本之间的兼容性问题 该工具是由 ceph-common-12.2.1.06-0.el7.centos.x86_64 rpm包生成 本文章是根据ceph-12.2.1版本来描述改…

EBS fnd_global.apps_initialize
原型:fnd_global.apps_initialize(user_ID, Responsibility_id,Responsibility_application_id);作用:在数据库的会话中设置全局变量,和用户概要信息。参数获得:参数一,用户ID select user_idfrom fnd_userwhere user_…