服务器性能测试二三事

原创内容,转载请注明出处

Posted by Weakyon Blog on January 7, 2015

新到手的机器,从运维手里交接必须要进行一些基本功能的测试。

对于我接手的小文件系统来说,最关键的就是磁盘和网络了。

一些有用的工具

这篇文章带了下fio和iperf但是没有详细介绍。

下面对fio稍微梳理一下

使用方式:

安装FIO
yum install gcc libaio-devel -y
wget http://brick.kernel.dk/snaps/fio-2.0.10.tar.gz
tar -zxvf fio-2.0.10.tar.gz
cd fio-2.0.10
make && make install

随机读:

fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=200G -numjobs=10 -runtime=1000 -group_reporting -name=mytest

参数说明:

filename=/dev/sda 测试文件名称,通常选择需要测试的盘的data目录。

direct=1 测试过程绕过机器自带的buffer。使测试结果更真实。

rw=randwrite 测试随机写的I/O

randread 随机读

read 顺序读

write 随机写

randrw 随机读写

bs=16k 单次io的块文件大小为16k

bsrange=512-2048 同上,提定数据块的大小范围

size=5g 本次的测试文件大小为5g,以每次4k的io进行测试。

numjobs=30 本次的测试线程为30.

runtime=1000 测试时间为1000秒,如果不写则一直将5g文件分4k每次写完为止。

ioengine= sync 使用read,write和fseek来读写文件

psync 使用pread和pwrite方式读写文件,这种方式读写完以后文件指针不会偏移特别适合随机读写

vsync 使用readv和writev方式读写文件,这种方式能把多个缓冲区的文件一次读写

libaio 使用linux的原生异步IO方式

posixaio 使用posix定义的aio_read和aio_write方式,这种方式在linux下使用pthread进行模拟异步IO,不是很高效

solarisaio solaris的aio

windowsaio windows的aio

mmap 使用内存映射方式,memcpy进行数据复制

splice 使用linux的splice传输数据,使用vmsplice在用户空间和内核之间传输数据

syslet 一个没啥用的异步IO方式

sg SCSI 通用的sg v3 I/O

null 不读写数据,测试fio本身用

net 网络方式,必须提供host/port,如果是接受,那么只有port参数会生效

netsplice 网络方式+splice方式

cpuio 不传递数据,但是安装cpu参数和周期消耗cpu周期

guasi the Generic Userspace Asynchronous Syscall Interface approach to asycnronous I/O.http://www.xmailserver.org/guasi-lib.html

rwmixwrite=30 在混合读写的模式下,写占30%

group_reporting 关于显示结果的,汇总每个进程的信息。

stonewall 等待前一个作业完成

此外

lockmem=1g 只使用1g内存进行测试。

zero_buffers 用0初始化系统buffer。

nrfiles=8 每个进程生成文件的数量。


这是我使用的test.fio脚本

[global]
size=200G
direct=1
iodepth=1
thread
runtime=60
group_reporting
write_bw_log=b
rw=randrw
ioengine=psync
bs=16k
numjobs=10
rwmixread=50

[random-1]
stonewall
filename=/dev/sdb

[random-2]
stonewall
filename=/dev/sdc

使用fio --output=test.log test.fio

测试完成后会输出一大段文字,主要看bw=18967KB/s, iops=1185这一段bw值就是吞吐率,以及iops的值


同时可以用iostat -xk测试

如下

avg-cpu:  %user   %nice    %sys %iowait   %idle
           0.42    0.00    0.26    0.47   98.86

Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
hdc          0.01   0.00  0.00  0.00    0.07    0.00     0.03     0.00    24.48     0.00    4.90   4.57   0.00
hda          0.89   8.54  0.74  4.49   12.60  104.22     6.30    52.11    22.32     0.03    5.41   1.01   0.53

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队列是非空的。

在从OS Buffer Cache传入到OS Kernel(Linux IO scheduler)的读IO操作的个数实际上是rrqm/s+r/s,直到读IO请求到达OS Kernel层之后,有每秒钟有rrqm/s个读IO操作被合并,最终转送给磁盘控制器的每秒钟读IO的个数为r/w;在进入到操作系统的设备层(/dev/sda)之后,计数器开始对IO操作进行计时,最终的计算结果表现是await,这个值就是我们要的IO响应时间了;svctm是在IO操作进入到磁盘控制器之后直到磁盘控制器返回结果所花费的时间,这是一个实际IO操作所花的时间,当await与svctm相差很大的时候,我们就要注意磁盘的IO性能了;而avgrq-sz是从OS Kernel往下传递请求时单个IO的大小,avgqu-sz则是在OS Kernel中IO请求队列的平均大小。

平均单次IO大小(IO Chunk Size) <=> avgrq-sz

平均IO响应时间(IO Response Time) <=> await

IOPS(IO per Second) <=> r/s + w/s

吞吐率(Throughtput) <=> rkB/s + wkB/s


别人一个不错的例子(I/O 系统 vs. 超市排队)

举一个例子,我们在超市排队 checkout 时,怎么决定该去哪个交款台呢? 首当是看排的队人数,5个人总比20人要快吧? 除了数人头,我们也常常看看前面人购买的东西多少,如果前面有个采购了一星期食品的大妈,那么可以考虑换个队排了。还有就是收银员的速度了,如果碰上了连 钱都点不清楚的新手,那就有的等了。另外,时机也很重要,可能 5 分钟前还人满为患的收款台,现在已是人去楼空,这时候交款可是很爽啊,当然,前提是那过去的 5 分钟里所做的事情比排队要有意义 (不过我还没发现什么事情比排队还无聊的)。

I/O 系统也和超市排队有很多类似之处:

r/s+w/s 类似于交款人的总数

平均队列长度(avgqu-sz)类似于单位时间里平均排队人的个数

平均服务时间(svctm)类似于收银员的收款速度

平均等待时间(await)类似于平均每人的等待时间

平均I/O数据(avgrq-sz)类似于平均每人所买的东西多少

I/O 操作率 (%util)类似于收款台前有人排队的时间比例。

我们可以根据这些数据分析出 I/O 请求的模式,以及 I/O 的速度和响应时间。

07 Jan 2015