前言
在日常的工作当中,经常会碰到Linux I/O层性能问题。简单梳理平时分析问题时的思路。做一个阶段性的回顾。
I/O下发流程
简单了解一下 I/O下发的流程
对于块设备来说,I/O可能由文件系统下发或者应用直接下发。下发可能会经过以下层次:
-
pagecache
文件系统下发的I/O一般会经过Page Cache,读I/O在命中缓存后会直接返回,写I/O会先预存在缓存当中,可以加快应用效率,缓解磁盘I/O -
dm/md
I/O进入到通用块层,如果块设备为虚拟设备,如dm-multipath设备,那么i/o会被remap到其它的块设备队列,这一层有自己的策略,同时可以嵌套 -
plug list
每个进程都有自己的plug list,当i/o被下发时,会先进入到plug list当中,并在此处尝试bio间的合并。此处不会做request合并。是否开启plug完全由内核决定,无法在用户态控制。 -
调度策略
i/o从plug list往下刷时,会交给调度策略,此处会尝试request queue之间的合并 。 -
驱动程序
调度策略将i/o转交给驱动程序。i/o完成后会通过中断通知操作系统。
分析思路
- 分析设备的压力来自于哪?
- 确认压力大小,i/o模型是否正常
- 分析设备的性能指标是否正常,和预期性能是否相符
- 针对单个i/o进行分析
- 外部因素(cpu/中断)
分析方法
确认压力来源
使用pidstat命令查看哪些进程正在生产压力
pidstat -d 1 10
-d为显示磁盘统计信息
1 10 为每隔一秒输出 ,共输出10秒
可以看到pid为34842的dd进程正在产生大量的写,每秒产生了238m的写。除此之外还有iotop等工具可以选择。
根据命令输出及业务环境,判断压力来源是否正常。是否有不合理的进程产生了大量的I/O影响业务性能。
分析压力、io模型是否正常
使用iostat命令查看io模型
iostat -dmx 1 10命令输出如下
dm-0设备对应的底层设备就是sda。
wareq-sz为平均写请求大小,单位为Kb。
w/s为每秒完成的写I/O数,统计值为合并后的值。
可以看到dm-0设备上wareq-sz为1024,说明每个io的大小是1M,w/s为234说明每秒有234个写i/o。总计每秒有234M的写。根据每个i/o的大小可以推测出i/o的模型为顺序写。
sda设备上每个i/o的大小是256k,说明i/o在从device-mapper层下发到裸设备时经历了拆分。
拆分的大小是由max_sectors_kb 参数决定的(/sys/block/sda/queue/max_sec_kb)
分析设备的性能指标是否正常
在iostat -dmx的输出当中,需要关注的性能指标有await/r_await/w_await/rrqm/wrqm。
await:平均每个IO所需要的时间,包括在队列等待的时间,也包括磁盘控制器处理本次请求的有效时间。
r_wait:每个读操作平均所需要的时间,不仅包括硬盘设备读操作的时间,也包括在内核队列中的时间。
w_wait: 每个写操平均所需要的时间,不仅包括硬盘设备写操作的时间,也包括在队列中等待的时间。
rrqm/wrqm:每秒排队到设备的合并读/写请求数。
想要知道块设备的性能正常不正常首先需要知道块设备的性能指标,以及大致的硬件环境,比如说是否经过RAID卡,有否做RAID,磁盘型号,NVMe是否为满带宽。知道硬件环境后,可以预估出一个大致性能。并且在环境上线前,必需要做一些压测明确块设备性能以及时延参数,以便后续维护。
对于盘性能指标,可以参考官网的性能参数。假如说块设备为远端设备,时延还会受到网络链路的影响。
使用sar -d可以查看历史io统计性能,进行压力分析与对比。
关于读写请求的合并可以通过调度策略控制。常见的调度策略有 noop deadline和cfq,多队列的调度策略有none mq-deadline kyber。关于调度策略的选择可以根据应用来,也可以根据存储介质类型进行选择,如nvme建议使用none。
查看I/O路径
使用btrace命令可以方便的观测i/o的每一个阶段。btrace其实就是blktrace用blkparse解析后的输出。从输出当中可以看到i/o的属性,从btrace当中的输出,可以更详细的分析i/o路径上是否有异常。同时它也可以查看到i/o的开始扇区以及大小。某些环境当中,i/o的扇区不对其、i/o大小与底层硬盘不一致都有可能会导致性能问题。
如上图当中,kworker进程产生了一个i/o,起始盲区地址为482262896,大小为208个扇区,也就是104kb。经过了Q - G - I - D -C阶段分别为
Q – 即将生成IO请求
|
G – IO请求生成
|
I – IO请求进入IO Scheduler队列
|
D – IO请求进入driver
|
C – IO请求执行完毕
blktrace命令使用可以参考http://bean-li.github.io/blktrace-to-report/
查看svctm统计值
拿dd来举例
先执行dd命令 dd if=/dev/zero of=/dev/root/test bs=1M count=10000 ofalg=direct
在dd命令执行的过程当中使用blktrace -d命令记录输出 blktrace -d /dev/sda,使用ctrl C中止
blkparse -i sda3 -d sda3.blktrace.bin
btt -i sda3.blktrace.bin #使用btt工具进行分析
大多数的时间都是位于D2C阶段,说明大多数的时间,都用于磁盘记录数据当中。如果大多数时间不是处于D2C阶段,那么说明系统出现了性能问题,可以查看多队列配置等问题。
系统资源使用
使用top命令观测系统当中的core使用,cat /proc/interrupts观测中断分部情况,进程申请不到内存。这些资源在部分情况下也会影响到i/o的性能。
常用命令
iotop
fdisk -l /dev/xxx
iostat -dmx 1 #I/O性能查看工具
grep "" /sys/block/xxx/queue/* #查看块设备属性
biosnoop -Q #查看I/O创建到发送到设备的时间
perf record -p xxxx #查看低I/O进程的堆栈
总结
- 压力
压力是否正常 pidstat / iotop - io模型、压力
iostat - 调度策略
cat /sys/block/xxx/queue/scheduler - i/o 拆分、每一阶段耗时
iostat / blktrace - 单个i/o分析
blktrace - 系统资源
top , cat /proc/interrupts , vmstat ,free 等
examples
慢慢补充