关于磁盘I/O测试工具Bonnie++的专题
作者简介:
张乐奕,通常使用的网名为kamus,也曾用过seraphim,现在任职于北京某大型软件公司,Oracle数据库DBA,主要负责证券行业的核心交易系统数据库管理及维护工作。
热切关注Oracle技术和相关操作系统技术,出没于各大数据库技术论坛,目前是中国最大的Oracle技术论坛www.itpub.net的数据库管理版版主。
阅读更多技术文章和随笔可以登录我的个人blog,http://blog.cdsn.net/kamus
目录
前言
最早是eygle在itpub上推荐这个工具,起因是我对于Sun的软RAID性能提出的置疑,后来eygle陆续用这个工具作了一些盘阵IO的测试,包括EMC和T3的一些比较。
这些测试结果都发表在eygle的个人站点上,见本文最后相关链接部分。
但是我却一直没有自己用Bonnie++测试过IO性能,最近一个客户要修改自己盘阵的RAID配置,本来就是使用D2的阵列,只能支持软RAID的一个性能比较差的古老东东了,在我们的测试过程中忽然又发现12块盘的盘阵配置的是RAID10,但是同时只有2块盘在作读写,也就是stripe设置只是2,这个问题在一年多以前刚上系统的时候就是这样,居然一直没有发现用了这么长时间。
客户最终决定重新设置一下RAID的配置,首先将redo和datafile分开,redo所在的盘用4块作RAID10,剩下8块再作RAID10,供数据文件使用,并且重新设置stripe,redo所在的lun设置为2,datafile所在的lun设置为4。
从理论上看,这样的修改应该会大幅度提到整个数据库的I/O效率,但是客户要求能够有一个实际的修改效果报告,也就是需要作修改前和修改后的对比。
这样,于是决定使用bonnie++来作磁盘级的修改效果报告。至于数据库级的修改效果自然有压力测试程序可以完成,此处不表。
既然决定使用,那么自然要琢磨一下该怎么用了。刚刚bonnie++已经开始运行了,于是闲下来,写了这篇文章。
安装
其实今天大部分的时间是耗在怎么让bonnie++运行起来上面了。
从bonnie++的主页上下载了最新的source,bonnie++1.03a.tgz。
gunzip bonnie++-1.03a.tgz
生成bonnie++-1.03a.tar文件,然后解包
tar xvf bonnie++-1.03a.tar
生成bonnie++-1.03a文件夹
cd bonnie++-1.03a
make
报错。
/usr/ucb/cc: language optional software package not installed
原来编译器就根本没装。
先介绍一下主机情况,一台SunFire v480,两块73G内置硬盘,4个UltraSPARC-III+的CPU,8G内存,安装的是Solaris8,由于需要模拟真实环境,所以安装的是比较老的02.2版本,而且没有打任何patch。
在Sun给的安装光盘中居然没有找到Companion CD,编译器应该是在这张盘上,没办法只好上网自己找,还好,很快就找到一个很棒的站点blastwave,包括了Solaris8,9的sparc和x86版本的所有需要的package。
根据gcc包下载页面中的说明,发现需要下载下面四个package。
common-1.3.3-SunOS5.8-sparc-CSW.pkg.gz
gcc3rt-3.3.3,REV=2004.04.23-SunOS5.8-sparc-CSW.pkg.gz
libiconv-1.8,REV=2003.01.12-SunOS5.8-sparc-CSW.pkg.gz
gcc3-3.3.3,REV=2004.03.22-SunOS5.8-sparc-CSW.pkg.gz
前面三个包是最后gcc3包的前提条件,必须安装。全部下载完毕,开始安装第一个包,也就是common那个包,报错。
提示操作系统的110934补丁版本过低,需要升级。
OK,再上网找,直接用google查,关键字是“110934 soalris”,通常前面几个link就会指向SunSolve站点的下载页面,patch通常不大,很快就下载完了。
开始打补丁,patchadd 110934-21。
系统运行半天,报错。
说要安装这个补丁就需要先安装110380-04的补丁。我倒。
再上网找,下载完110380-04,先patchadd 110380-04,一切正常。
再重新patchadd 110934-21,一切正常。
打完补丁以后,重新安装common包,OK,一切正常。
pkgadd -d common-1.3.3-SunOS5.8-sparc-CSW.pkg.gz
然后依次安装其它的包,一切正常。
这个包将gcc安装到/opt/csw/gcc3目录下。
说明文件指出安装完gcc将创建/opt/csw/bin下的gcc执行程序,所以要求将这个路径加入用户的PATH变量中,但是实际上安装完gcc3.3的版本以后,并没有在上面的路径中生成任何文件。
后来我再安装gcc2.95版本的时候发现这个版本的安装才是将gcc生成到/opt/csw/bin中。
所以如果我们在Solaris8中即安装了gcc2.95又安装了gcc3.3,那么要注意这两个版本的gcc文件在不同的路径下,其实这也是应该的,否则新版本会覆盖旧版本,往往是很多人不愿意的。
回到上面,安装完gcc3以后,再次运行make,仍然报错。
/usr/ucb/cc: language optional software package not installed
检查PATH环境变量,已经将/opt/csw/gcc3/bin目录加入了。
想了一下,感觉应该是系统还在使用原来的/usr/ucb/cc。于是将cc链接到新安装的gcc上,这样无论什么时候调用cc其实都是直接使用gcc了。
whereis cc
cd /usr/ucb
mv cc cc.org
ln -s /opt/csw/gcc3/bin/gcc /usr/ucb/cc
备注:如果要安装gcc2的包,那么需要下载下面两个package。
gcc2rt-2.95.3,REV=2003.03.01-SunOS5.8-sparc-CSW.pkg.gz
gcc2-2.95.3-SunOS5.8-sparc-CSW.pkg.gz
安装完毕以后,同样是将cc链接到这个版本的gcc上。
whereis cc
cd /usr/ucb
mv cc cc.org
ln -s /opt/csw/bin/gcc /usr/ucb/cc
修改完毕以后编译成功。
运行bonnie++,报错。
libstdc++.so.5: cannot open shared object file: No such file or directory.
继续查资料,发现bonnie++寻找的lib路径是环境变量LD_LIBRARY_PATH指定的路径,但是这个路径下并没有libstdc++.so.5文件,于是手工将libstdc++.so.5文件从gcc3的安装路径中ln到/usr/lib下面。
# ln -s /opt/csw/gcc3/lib/libstdc++.so.5 /usr/lib/libstdc++.so.5
再次运行,仍然报错。
libgcc_s.so.1: cannot open shared object file: No such file or directory.
这次就轻车熟路了,直接再作一次link。
# ln -s /opt/csw/gcc3/lib/libgcc_s.so.1 /usr/lib/libgcc_s.so.1
终于,bonnie++可以正常运行了。
我们可以不需要自己编译,在eygle的站点上有Solaris8下载编译好的bonnie++。直接可以使用,当然如果运行报libstdc++.so.5找不到的问题,还需要按照上面的方法解决。
使用.
接下来继续介绍bonnie++(Version: 1.03)的使用方法以及结果的含义。
usage: bonnie++ [-d scratch-dir] [-s size(Mb)[:chunk-size(b)]]
[-n number-to-stat[:max-size[:min-size][:num-directories]]]
[-m machine-name]
[-r ram-size-in-Mb]
[-x number-of-tests] [-u uid-to-use:gid-to-use] [-g gid-to-use]
[-q] [-f] [-b] [-p processes | -y]
首先说明一下命令中常用的参数。
-d 生成测试文件的路径
-s 生成测试文件的大小,以M为单位(如果不使用-r参数,则要求文件大小至少是系统物理内存的2倍)
-m 机器名,实际上我们可以认为是本次测试的方案名,可以随便定义。默认是本机的hostname。
-r 内存大小,指定内存大小,这样可以通过-s参数创建r*2大小的文件,通常用于缩短测试时间,但是需要注意这样由于内存的cache可能导致测试结果的不准确
-x 测试的次数
-u 测试文件的属主和组,默认是执行bonnie++的当前用户和当前组
-g 测试文件的组,默认是执行bonnie++的当前用组
-b 在每次写文件时调用fsync()函数,对于测试邮件服务器或者数据库服务器这种通常需要同步操作的情况比较适合,而不使用该参数则比较适合测试copy文件或者编译等操作的效率。
通常我们可以简单地运行如下命令进行磁盘性能测试:
bonnie++ -d /global/oradata –m sun3510
这样将会在指定的目录下(通常我们会指定一个盘阵上卷的挂载点),生成相当于主机物理内存两倍的文件,如果总量大于1G,则生成多个大小为1G的文件。假设主机内存为4G,那么在测试中就会生成8个1G的文件,到测试结束,这些文件会被自动删除。
如果我们的主机内存是4G,但是我们想缩短测试的时间,比如说只写2G的文件,就应该执行下面的命令:
bonnie++ -d /global/oradata –m sun3510 –s 2048 –r 1024
bonnie++的在测试的时候通常会占用大量的IO和CPU,所以请不要在生产环境的业务高峰期进行测试。
下面看一个测试结果,通过这个结果我们解释一下到底bonnie++在测试过程中都作了什么,而每一个输出的结果又表示了什么。
这个测试结果是在一台SunFire V880 + D2阵列上进行的,主机配置是2个UltraSparc-III+ 900MHz的CPU,4G内存,而D2阵列是满配的12块36G SCSI磁盘,划分了两个LUN,我们的测试目的地/global/oradata建立在其中的一个LUN上,使用了8块磁盘,用Veritas Volum Manager作了RAID10,stripe(也就是ncol)设置为4。
bonnie++ -d /global/oradata -s 8192 -m d2new -u oracle
Using uid:1001, gid:101.
Writing with putc()...done
Writing intelligently...done
Rewriting...done
Reading with getc()...done
Reading intelligently...done
start 'em...done...done...done...
Create files in sequential order...done.
Stat files in sequential order...done.
Delete files in sequential order...done.
Create files in random order...done.
Stat files in random order...done.
Delete files in random order...done.
Version 1.03 ------Sequential Output------ --Sequential Input- --Random-
-Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
d2new 8G 18275 62 32832 26 25423 55 27444 94 106842 60 549.9 7
------Sequential Create------ --------Random Create--------
-Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 1723 15 +++++ +++ 5059 40 4821 37 +++++ +++ 653 5
依次解读一下,从Writing with putc()开始到Delete files in random order…结束,这是bonnie++作的12项测试,这12项测试依次对应12项结果,而这12项结果又被分为了5大类,分别是Sequential Output(写测试),Sequential Input(读测试),Random Seeks(读写测试),Sequential Create(顺序读写文件测试)和Random Create(随意读写文件测试)。
那么测试步骤和测试结果依次对应的顺序就是:
Writing with putc() -> Sequential Output的Per Chr
Writing intelligently -> Sequential Output的Block
Rewriting -> Sequential Output的Rewrite
Reading with getc() -> Sequential Input的Per Chr
Reading intelligently -> Sequential Input的Block
start 'em -> Random Seeks
Create files in sequential order -> Sequential Create的Create
Stat files in sequential order -> Sequential Create的Read
Delete files in sequential order -> Sequential Create的Delete
Create files in random order -> Random Create的Create
Stat files in random order -> Random Create的Read
Delete files in random order -> Random Create的Delete
每个结果中又包括了2项数值,一个是K字节数或者文件数,另一个是%CP,就是执行这项测试时CPU的平均占用率。
对于输出结果的评价,我们认为在相等CPU的占用率情况下,存取字节数越高表示该存储设备的吞吐量越大,自然性能也就越好。
值得注意的是,在测试RAID的时候,对于多CPU的系统,bonnie++并没有发挥CPU的最大潜力,也就是说bonnie++发出的I/O请求通常不够达到CPU和磁盘的最大压力,这时候显示的吞吐量就不是这个存储设备能够达到的最大值。我们可以在测试的同时通过iostat,mpstat,sar等命令监控系统状况,如果没有明显的I/O等待,通常表示测试软件的压力不够。在bonnie++的主页上也表示对于多CPU多进程的支持将放到2.0版本中去实现。
明白了测试步骤和测试结果之后,我们再来进一步看看每个测试结果都是什么含义。
Sequential Output
1. Per Char
就是Per-Character的含义。使用putc()函数进行循环写入,每次写入的字节很小,基本上可以放入任意一种I-Cache中,这种情况下的CPU消耗在处理putc()代码和分配磁盘文件空间上。
2. Block
使用write(2)函数创建文件。这种情况下的CPU消耗只是在分配磁盘文件空间上。
3. Rewrite
使用read(2)函数读取文件,然后修改再用write(2)函数写回。由于文件的空间已经分配好,所以这种方式可以很有效地测试文件系统缓存和数据传输的速度。
Sequential Input
1. Per Char
使用getc()函数循环 读取文件内容
2. Block
使用read(2)函数循环读取文件内容,有效测试磁盘读取的效率。
Random Seek
默认3个进程作8000次的测试。用read(2)函数读取文件的block,同时有10%的操作是用write(2)函数将block修改以后写回文件中。在这个测试中,如果内存容量大于创建的文件大小,那么将会出现比较高的数值,而这个数值可能并不能准确反映磁盘本身的I/O效率。
Sequential Create和Radom Create
这两大类测试均是用创建,读取,删除大量的小文件来测试磁盘效率。文件名用7位数字和任意个数(0-12)的任意英文字母来组成。在Sequential部分,字母在数字之后,而Random部分则是字母在数字之前。
创建文件的最小值和最大值等参数可以在bonnie++命令行中用-n参数来控制。
评测.
我们通过bonnie++来测试各种磁盘配置,或者测试各种RAID设置下的磁盘效率,可以有助于我们对于各个产品或者各个方案的磁盘吞吐效率有个大体认识。
在测试结果的最后一行是用逗号隔开的一列数字,第一个位置是我们在运行bonnie++时用-m参数指定的机器名,第二个位置是测试时生成的文件大小,后面依次是各类测试的结果。我们将多个测试的最后一行粘贴到Excel中,然后用图表功能生成柱状图,就可以对多项测试有一个极为直观的评测比较。
下面列出了几种评测的结果,以后也会陆续添加更多的评测,同时欢迎大家将自己的评测结果mail给我,我会加入到这篇文章中。我的邮件地址是kamus@itpub.net。
SunFire v480 4*(UltraSparc-III+ 1050MHz) 8GRAM 本地光纤硬盘
>bonnie++ -d . -s 16384 -m report -u oracle:dba
Version 1.03 ------Sequential Output------ --Sequential Input- --Random-
-Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
report 16G 18703 52 28812 17 10800 12 33700 98 68172 32 260.1 2
------Sequential Create------ --------Random Create--------
-Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 99 0 +++++ +++ 166 1 101 0 +++++ +++ 205 1
report,16G,18703,52,28812,17,10800,12,33700,98,68172,32,260.1,2,16,99,0,+++++,+++,166,1,101,0,+++++,+++,205,1
SunFire v880 2*(UltraSparc-III+ 900MHz) 4GRAM D2阵列(36G*12,RAID10,2 stripe)
>bonnie++ -d /global/oradata -s 8192 -m d2org -u oracle
Version 1.03 ------Sequential Output------ --Sequential Input- --Random-
-Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
d2org 8G 15681 55 26302 23 13877 31 26420 91 88215 49 462.6 5
------Sequential Create------ --------Random Create--------
-Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 1245 10 +++++ +++ 3541 27 2837 21 +++++ +++ 385 3
d2org,8G,15681,55,26302,23,13877,31,26420,91,88215,49,462.6,5,16,1245,10,+++++,+++,3541,27,2837,21,+++++,+++,385,3
SunFire v880 2*(UltraSparc-III+ 900MHz) 4GRAM D2阵列(36G*8,RAID10,4 stripe)
>bonnie++ -d /global/oradata -s 8192 -m d2new -u oracle
Version 1.03 ------Sequential Output------ --Sequential Input- --Random-
-Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
d2new 8G 18275 62 32832 26 25423 55 27444 94 106842 60 549.9 7
------Sequential Create------ --------Random Create--------
-Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 1723 15 +++++ +++ 5059 40 4821 37 +++++ +++ 653 5
d2new,8G,18275,62,32832,26,25423,55,27444,94,106842,60,549.9,7,16,1723,15,+++++,+++,5059,40,4821,37,+++++,+++,653,5
相关链接
bonnie++主页
http://www.coker.com.au/bonnie++/
对各种操作系统下磁盘I/O测试软件的专题站点
http://www.acnc.com/04_02_01.html
该站中还有各种类型RAID的概念描述,优缺点,包括图示,值得一看
http://www.acnc.com/04_00.html
关于磁盘I/O测试的专题讨论
http://www.itpub.net/266416.html
eygle个人站点上有关bonnie++的文章