性能测试中磁盘IO的监控及分析
简介
对于性能测试来说,服务器资源的监控是必不可少的一部分,分为CPU、内存、磁盘IO和网络吞吐,其中磁盘IO是比较复杂的一项,需要我们细化监控分析,影响磁盘IO的因素也是多种的,其中最常见的为存储设备的效率影响、程序代码设计层面、操作系统参数层面等,那我们就来详细了解下其监控分析的过程。
磁盘IO简介
什么是磁盘 IO?举个简单的例子,当你程序的运行,内存中不存在,这个时候应用程序就会触发系统调用,去磁盘中读取相应的数据加载到内存中。这个过程就是一个经典的磁盘 IO。
磁盘IO的监控方法
1)top命令
top 命令通过查看 CPU 的 wa% 值来判断当前磁盘 IO 性能。如果这个数值过大,很可能是磁盘 IO 过高,磁盘IO排队处理导致CPU wa%较高。
备注:如果wa%较高的情况下,会影响整体CPU%,因此对于CPU%的使用要进行细化监控统计。
2)iostat命令
使用 iostat 查看磁盘的IO的使用,iostat -x 1或者iostat -xn 1,1代表1秒中采集一次。
各个监控结果项解释:
rrqm/s:每秒进行 merge 的读操作数目。
wrqm/s:每秒进行 merge 的写操作数目。
r/s:每秒完成的读 I/O 设备次数。
w/s:每秒完成写 I/O 设备次数。
rsec/s:每秒读扇区数。
wsec/s:每秒写扇区数。
rKB/s:每秒读K字节数。
wKB/s:每秒写K字节数。
avgrq-sz:平均每次设备 I/O 操作的数据大小(扇区)。
avgqu-sz:平均 I/O 队列长度
await:平均每次设备 I/O 操作的等待时间(毫秒)。
svctm:平均每次设备 I/O 操作的服务时间(毫秒)。
%util:一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。
3)sar命令
可以通过sar -d 1 100 命令采集,每 1秒 间隔采样 100 次:
sar的监控结果各项的含义跟iostat类似,可以参考iostat的解释。
4)pidstat命令
pidstat -d 1,实时监控全部或指定进程占用系统资源的情况,pidstat -d 1 按照磁盘 IO 每秒刷新一次,显示各个进程的 IO 使用情况:
5)lsof命令
lsof -p pid,通过命令,找到问题进程正在读写的文件信息,并定位性能问题的根源。
通过 -p 选项并指定进程的 PID 可以输出该进程打开的所有文件。比如我们想要查看 xx程序打开的文件,可以先用 ps -C xx命令查出进程的 PID,然后把该 PID 传递给 lsof 命令的 -p 选项。
各个结果输出项解释:
COMMAND:程序的名称
PID:进程标识符
USER:进程所有者
FD:文件描述符,应用程序通过文件描述符识别该文件
TYPE:文件类型,如 DIR、REG 等
DEVICE:以逗号分隔设备编号
SIZE:文件的大小(bytes)
NODE:索引节点(文件在磁盘上的标识)
NAME:打开文件的确切名称
6)iotop命令
iotop 用来监视磁盘 IO 使用状况,是一个类似 top 的工具,用来显示实时的磁盘活动。
iotop -d 2 -n 5
,每 2秒 间隔采样 5 次。
iotop -botq -p PID
指定PID进行细化监控
iotop的各个参数说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | -o, --only只显示正在产生I/O的进程或线程。除了传参,可以在运行过程中按o生效。 -b, --batch非交互模式,一般用来记录日志。 -n NUM, --iter=NUM设置监测的次数,默认无限。在非交互模式下很有用。 -d SEC, --delay=SEC设置每次监测的间隔,默认1秒,接受非整形数据例如1.1。 -p PID, --pid=PID指定监测的进程/线程。 -u USER, --user=USER指定监测某个用户产生的I/O。 -P, --processes仅显示进程,默认iotop显示所有线程。 -a, --accumulated显示累积的I/O,而不是带宽。 -k, --kilobytes使用kB单位,而不是对人友好的单位。在非交互模式下,脚本编程有用。 -t, --time 加上时间戳,非交互非模式。 -q, --quiet 禁止头几行,非交互模式。有三种指定方式。 -q 只在第一次监测时显示列名 -qq 永远不显示列名。 -qqq 永远不显示I/O汇总。 交互按键: 和top命令类似,iotop也支持以下几个交互按键。 left和right方向键:改变排序。 r:反向排序。 o:切换至选项--only。 p:切换至--processes选项。 a:切换至--accumulated选项。 q:退出。 i:改变线程的优先级。 |
磁盘IO的优化方向
1)应用程序设计
根据操作系统设计原理,当应用程序需要读取文件中的数据时,尽量保证:
a、避免磁盘的随机 IO , 充分利用磁盘预读缓存和局部性原理。
b、尽可能地顺序读写一个文件
c、单进程读写硬盘。
d、避免对大目录读写。
e、把小文件转换为大文件读写。
2)操作系统参数
a、vm.dirty_background_ratio= 0 内核往磁盘同步脏页的阈值(百分比)
b、vm.dirty_background_bytes = 1048576 内核往磁盘同步脏页的字节阈值
c、vm.dirty_ratio = 0 当程序不停向page cache写入数据达到这个阈值,就会阻塞,开始写入磁盘。
d、vm.dirty_bytes = 1048576 当程序不停向page cache写入数据达到这个字节限制阈值,就会阻塞,写入磁盘
e、vm.dirty_writeback_centisecs = 5000 脏页写入磁盘的时间(单位:0.01秒)
f、vm.dirty_expire_centisecs = 30000 脏页的生命周期可以存多久(单位:0.01秒)
3)数据库设计
a、数据库的表设计缺陷,表的分类以及对应的块大小和页大小设计不合理。
b、数据库的bufferpool设置过小,或者使用不当导致命中率低。
c、数据库的SQL编写冗余度高,索引使用不当
Q&A
1)Q:当程序写操作运行结束,数据是否已经写入磁盘?
A:答案是否定的,写操作也是受到操作系统内核的限制,在操作系统内核没有触发刷盘操作时,数据是没有真正持久化到磁盘中,依然有丢失数据的问题存在。
2)Q:为什么有 buffer 的 IO 比普通 IO 的数据快?
A:主要是因为普通的 IO 频繁触发了系统调用,而在 JVM 中只有 buffer 满了,才会触发系统调用,将数据写入磁盘中。
3)Q:当频繁的往一个文件中写入数据,是否会存在内存中?
A:当内存空间足够时,数据会存在内存中。当内存空间不够时,会优先淘汰掉最早写入的数据。
4)Q:mmap 是否可以不需要操作系统内核直接写入数据?
A:不可以。mmap 也需要受到内核系统的约束。