现有的测试工具分为三类:合成IO测试、基准测试集、基于Trace的测试。
合成测试程序根据统计的真实负载发生规律,如请求的读写比例,大小,频率和分布等信息。建立响应的io存取模型。在测试时产生符合存取模型的io请求序列。发送给存储系统。这类程序包括 IOMeter,IOZone 和 Bonnie++。使用基准测试集测试计算机系统的性能,一直是有效和精确的评价方法。针对存储系统的测试研究也大量使用基准测试集。
存储性能委员会SPC,为存储系统开发了基准测试集。SPC-1 SPC-2; 标准性能评价组织SPEC 标准集成立于1988,目标是建立标准和实际的性能测试集。其中 SFS是测量NFSv2和NFSv3服务器的性能,包括吞吐率和响应时间。它在客户端上运行实现定义的负载脚本产生各种实际的文件和目录操作。
Trace测试。Trace 测试是搜集真实系统中所有的IO请求信息,并按照一定格式记录在Trace文件中,一般包括请求时间,请求类型和请求大小等。测试时,程序按照Trace文件中的记录想存储系统中发出IO请求。但是记录Trace信息会增加IO开销。
对于一个测试工具来说,需要满足一下几个基本要求:
- 一是对不同系统进行测试所得到的结果具有可比较性。
- 二是可移植性好,能够适应或者非常方便的移植到不同的机器上;
- 三是测试结果准确客观。
影响测试软件网络带宽测试结果的关键因素有:读写操作比例,测试数据总大小,测试过程中每次操作的数据大小,顺序或者随机访问模式,多个测试进程同时访问一个文件还是访问各自独立的文件,或称之为共享或者并发访问模式。
一、pjd-fstest (posix 接口兼容性测试)
fstest是一套简化版的文件系统POSIX兼容性测试套件,它可以工作在FreeBSD, Solaris, Linux上用于测试UFS, ZFS, ext3, XFS and the NTFS-3G等文件系统。fstest目前有3601个回归测试用例,测试的系统调用覆盖chmod, chown, link, mkdir, mkfifo, open, rename, rmdir, symlink, truncate, unlink。
使用方法:
- 解压压缩包 有两个版本 建议使用 08 稳定版;
- 参照软件说明文档;
具体步骤如下:
# cd fstest # vi tests/conf Change 'fs' to file system type you want to test. These can be: UFS, ZFS, ext3, ntfs-3g and xfs. # vi Makefile You may need to manually tweak few things by editing CFLAGS lines at the top of the file. # make It will compile fstest utility which is used by regression tests. # cd /path/to/file/system/you/want/to/test/ The test must be run as root user. # prove -r /path/to/fstest/
测试结果:
注:prove 为测试命令; 位于 perl-Test-Harness 工具包中;fedora/centos 用户可以使用 yum/dnf 安装;
二、 IOZone (读写模式测试)
磁盘设备之上是文件系统,测试磁盘的工具往往就是调用块设备驱动的接口进行读写测试。而文件系统的测试软件就是针对文件系统层提供的功能进行测试,包括文件的打开关闭速度以及顺序读写随机位置读写的速度。以及进程并发数目等各个方面进行详细的测试。
IOZone是目前应用非常广泛的文件系统测试标准工具,它能够产生并测量各种的操作性能,包括read, write, re-read, re-write, read backwards, read strided, fread, fwrite, random read, pread ,mmap, aio_read, aio_write等操作。Iozone目前已经被移植到各种体系结构计算机和操作系统上,广泛用于文件系统性能测试、分析与评估的标准工具。
IOZone和IOMeter不同,IOMeter的测试是基于数据块的,而IOZome的测试是基于文件的,因此更适合用来测试文件系统的性能。使用IOZone 可以在多线程,多CPU,并指定CPU Cache 空间大小以及同步或者异步IO读写模式的情况下进行文件操作的性能测试。
下载:可以在参考链接进行下载;在写此博文是 iozone的版本为3 487;下载为 压缩包,解压后,根据软件说明文档可以进行编译生成 对应平台的 测试文件;
常用参数:(具体参数,可以参考iozone 文档,该文档较为详细)
-a 全面测试,比如块大小它会自动加; -i N 用来选择测试项(具体参数,后面有详细描述); -r block size 制定一次写入/读出的块大小; -s file size 制定测试文件的大小; -f filename 制定测试文件的名字,完成后会自动删除; -F file1 file2….. 多线程下测试的文件名; -g –n 指定测试文件大小范围。-n 后接最小值,-g 后接最大值 ,如测试512m-4G:-n 512m –g 4G; -y –q 指定测试块的大小范围; -R 产生excel到标准输出; -b 制定将结果输出到制定文件上,比如:-Rb test.xls;
-i # 的详细选项:
Used to specify which tests to run. (0=write/rewrite, 1=read/re-read, 2=random-read/write 3=Read-backwards, 4=Re-write-record, 5=stride-read, 6=fwrite/re-fwrite, 7=fread/Re-fread, 8=random mix, 9=pwrite/Re-pwrite, 10=pread/Re-pread, 11=pwritev/Re-pwritev, 12=preadv/Repreadv). One will always need to specify 0 so that any of the following tests will have a file to measure. -i # -i # -i # is also supported so that one may select more than one test.
使用:
我们可以把生成的iozone 可执行文件拷贝到需要运行挂载点进行运行。也可以使用 -f 指定路径;
常用命令:
iozone –Ra iozone –Rab output.wks iozone –Ra –g 2G –i 0 –i 1
iozone –Rac (NFS 使用)注意此时-c 标志在nfs中的使用:
-c 标志的含义
使用范例:
在current目录下,执行测试指令
[root@localhost current]# ./iozone -a -n 1g -g 4g -i 0 -f /test.txt -Rb ./test.xls
说明:
./iozone:运行iozone工具; -a:进行全面测试; -n 1g:测试最小文件为1g; -g 4g: 测试最大文件为4g; -I 0:测试模式为写; -f:测试文件为:/test.txt; -Rb:将测试结果放入test.xls;
测试结果如下图所示:
测试结果分析:
在excel文件中,说明了这个表单关于write的测试结果,最左侧一列是测试文件的大小(Kbytes);最上的横行,是记录大小;中间数据是测试的传输数据。
如,213749:表示测试文件大小为1G,以记录大小为1m来进行传输,它的传输速度为213749kbytes/s。
常用测试命令:
./iozone -R -a -b hvs-iozone.xls -c -i 0 -i 1 -i 2 -i 3 -i 4 -i 5 -i 8
该命令中,-a表示使用全自动模式进行测试,并根据测试结果生成excel测试文件,程序生成的所有测试单次操作从4k到16M不等;文件尺寸从64k到512m不等;测试中-c表示包含close操作的时间,这在网络文件系统中起到一定作用。命令中表示对 0=write/rewrite, 1=read/re-read,2=random-read/write,3=Read-backwards,4=Re-write-record, 5=stride-read, 8=random mix 这几种读写模式进行测试;测试结果输出在命令行中,同时在输出 hvs-iozone.xls 文件中;
三、FIO (磁盘IO测试-顺序IO和随机IO)
fio是一个I/O标准测试和硬件压力验证工具,它支持13种不同类型的I/O引擎(sync, mmap, libaio, posixaio, SG v3, splice, null, network, syslet, guasi, solarisaio等),I/O priorities (for newer Linux kernels), rate I/O, forked or threaded jobs等等。fio可以支持块设备和文件系统测试,广泛用于标准测试、QA、验证测试等,支持Linux, FreeBSD, NetBSD, OS X, OpenSolaris, AIX, HP-UX, Windows等操作系统。
Multithreaded IO generation tool , FIO 是一个多线程io生成工具,可以生成多种IO模式,用来测试磁盘设备的性能(也包含文件系统:如针对网络文件系统 NFS 的IO测试);
安装:
yum install fio yum info fio apt install gfio # fio 图形测试工具
磁盘处理:
fio 用于测试磁盘性能时,测试之前需要先把要测试的磁盘卸载掉,测试完后需格式化一遍再挂载上去。
# 卸载磁盘 umount /mnt/datadir1 # 格式化磁盘 mkfs.ext4 /dev/sdd # 挂载磁盘 mount -t ext4 /dev/sdd /mnt/datadir1 # 自动挂载,在里面添加该盘 vim /etc/fstab
FIO 工具常用方法:
参数说明: filename=/dev/sdb1 测试文件名称,通常选择需要测试的盘的data目录。 direct=1 测试过程绕过机器自带的buffer。使测试结果更真实。 rw=randwrite 测试随机写的I/O rw=randrw 测试随机写和读的I/O bs=16k 单次io的块文件大小为16k bsrange=512-2048 同上,提定数据块的大小范围 size=5g 本次的测试文件大小为5g,以每次4k的io进行测试。 numjobs=30 本次的测试线程为30. runtime=1000 测试时间为1000秒,如果不写则一直将5g文件分4k每次写完为止。 ioengine=psync io引擎使用pync方式 rwmixwrite=30 在混合读写的模式下,写占30% group_reporting 关于显示结果的,汇总每个进程的信息。 此外 lockmem=1g 只使用1g内存进行测试。 zero_buffers 用0初始化系统buffer。 nrfiles=8 每个进程生成文件的数量。 磁盘读写常用测试点: 1. Read=100% Ramdon=100% rw=randread (100%随机读) 2. Read=100% Sequence=100% rw=read (100%顺序读) 3. Write=100% Sequence=100% rw=write (100%顺序写) 4. Write=100% Ramdon=100% rw=randwrite (100%随机写) 5. Read=70% Sequence=100% rw=rw, rwmixread=70, rwmixwrite=30 (70%顺序读,30%顺序写) 6. Read=70% Ramdon=100% rw=randrw, rwmixread=70, rwmixwrite=30 (70%随机读,30%随机写)
FIO 工具测试模式:
顺序读写:
read 顺序读 write 顺序写 rw,readwrite 顺序混合读写
随机读写:
randwrite 随机写 randread 随机读 randrw 随机混合读写
测试样例:
[root@docker mnt]# fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=20G -numjobs=30 -runtime=1000 -group_reporting -name=yaoxu-sda
测试结果:(其中加粗的输出日志,是我们关注的内容:磁盘的吞吐量bw,这个是顺序读写考察的重点;磁盘的每秒读写次数iops,这个是随机读写考察的重点)
[root@docker sda]# fio -ioengine=libaio -bs=4k -direct=1 -thread -rw=read -filename=/dev/sda -name="BS 4KB read test" -iodepth=16 -runtime=60 BS 4KB read test: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=16 fio-3.7 Starting 1 thread Jobs: 1 (f=1): [R(1)][100.0%][r=89.3MiB/s,w=0KiB/s][r=22.9k,w=0 IOPS][eta 00m:00s] BS 4KB read test: (groupid=0, jobs=1): err= 0: pid=18557: Thu Apr 11 13:08:11 2019 read: IOPS=22.7k, BW=88.5MiB/s (92.8MB/s)(5313MiB/60001msec) slat (nsec): min=901, max=168330, avg=6932.34, stdev=1348.82 clat (usec): min=90, max=63760, avg=698.08, stdev=240.83 lat (usec): min=97, max=63762, avg=705.17, stdev=240.81 clat percentiles (usec): | 1.00th=[ 619], 5.00th=[ 627], 10.00th=[ 627], 20.00th=[ 635], | 30.00th=[ 635], 40.00th=[ 685], 50.00th=[ 717], 60.00th=[ 725], | 70.00th=[ 725], 80.00th=[ 725], 90.00th=[ 734], 95.00th=[ 816], | 99.00th=[ 1004], 99.50th=[ 1020], 99.90th=[ 1057], 99.95th=[ 1057], | 99.99th=[ 1860] bw ( KiB/s): min=62144, max=91552, per=100.00%, avg=90669.02, stdev=3533.77, samples=120 iops : min=15536, max=22888, avg=22667.27, stdev=883.44, samples=120 lat (usec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=93.85%, 1000=5.14% lat (msec) : 2=0.99%, 4=0.01%, 10=0.01%, 50=0.01%, 100=0.01% cpu : usr=5.35%, sys=23.17%, ctx=1359692, majf=0, minf=17 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=100.0%, 32=0.0%, >=64=0.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.1%, 32=0.0%, 64=0.0%, >=64=0.0% issued rwts: total=1360097,0,0,0 short=0,0,0,0 dropped=0,0,0,0 latency : target=0, window=0, percentile=100.00%, depth=16 Run status group 0 (all jobs): READ: bw=88.5MiB/s (92.8MB/s), 88.5MiB/s-88.5MiB/s (92.8MB/s-92.8MB/s), io=5313MiB (5571MB), run=60001-60001msec Disk stats (read/write): sda: ios=1357472/0, merge=70/0, ticks=949141/0, in_queue=948776, util=99.88%
- io=执行了多少M的IO
- bw=平均IO带宽
- iops=IOPS
- runt=线程运行时间
- slat=提交延迟
- clat=完成延迟
- lat=响应时间
- bw=带宽
- cpu=利用率
- IO depths=io队列
- IO submit=单个IO提交要提交的IO数
- IO complete=Like the above submit number, but for completions instead.
- IO issued=The number of read/write requests issued, and how many of them were short.
- IO latencies=IO完延迟的分布
- io=总共执行了多少size的IO
- aggrb=group总带宽
- minb=最小.平均带宽
- maxb=最大平均带宽.
- mint=group中线程的最短运行时间
- maxt=group中线程的最长运行时间
- ios=所有group总共执行的IO数.
- merge=总共发生的IO合并数
- ticks=Number of ticks we kept the disk busy
- io_queue=花费在队列上的总共时间
- util=磁盘利用率
fio 有很多测试任务配置文件,在git工程 examples 文件夹中,我们可以使用命令行参数进行直接配置,也可以直接通过配置文件配置一次测试的内容。
IO状态监控:
进行磁盘测试的时候,我们可以使用iostat 等监控工具,查看所有磁盘当前的读写状态(fedora 系统上 sysstat-11.7.3-2.fc29.x86_64 收录了此工具)。
监控磁盘IO命令:iostat –mx 1
vg-cpu: %user %nice %system %iowait %steal %idle 0.25 0.00 3.01 80.70 0.00 16.04 Device r/s w/s rMB/s wMB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util sda 13417.00 0.00 209.64 0.00 0.00 0.00 0.00 0.00 2.23 0.00 29.96 16.00 0.00 0.07 100.00
View Code
四、Filebench (文件系统应用负载生成测试)
Filebench 是一款文件系统性能的自动化测试工具,它通过快速模拟真实应用服务器的负载来测试文件系统的性能。它不仅可以仿真文件系统微操作(如 copyfiles, createfiles, randomread, randomwrite ),而且可以仿真复杂的应用程序(如 varmail, fileserver, oltp, dss, webserver, webproxy )。Filebench 比较适合用来测试文件服务器性能,但同时也是一款负载自动生成工具,也可用于文件系统的性能。
安装:
Make sure bison and lex are available in your system. Then, run traditional configure, make, and sudo make install commands.
fedora 上 使用 yum 工具,即可以安装稳定版;
安装最新版需要下载 flex 和 bison 等依赖;
yum install flex bison
$cd /usr/local/filebench-1.5-alpha3 (源文件所在的路径) $./configure $make $sudo make install (注意:一定要安装 filebench 需要在/usr/local/share/filebench 下生成一些文件)
使用:
filebench 需要根据 WML 负载模型语言来进行描述负载,然后来进行执行。所以我们可以使用已经预定好的负载,也可以自己定义自己的负载模型,然后运行。
命令:filebench -f /usr/local/share/filebench/workloads/fileserver.f
测试结果:
当然,我们不建议直接使用 原有的文件进行测试。我们可以在原有的wml文件基础上根据我们自己的使用场景来定义负载。
FileBench架构:
五、Mdtest (元数据性能测试)
Mdtest 是一个测试文件系统元数据性能的工具。
IOR 设计用于测量POSIX和MPI-IO级别的并行文件系统的I/O的性能;mdtest 被设计用于测试文件系统的元数据性能并生成测试报告;mdtest 工具已经变成了ior 工具的一部分了。我们可以安装ior套件,并使用 其中mdtest命令来进行测试文件系统元数据的性能;该工具由美国洛斯阿拉莫斯国家实验室(Los Alamos National Laboratory)开发并开源,具有较高的权威性;
安装说明:
- If
configure
is missing from the top level directory, you probably retrieved this code directly from the repository. Run./bootstrap
to generate the configure script. Alternatively, download an official IOR release which includes the configure script. - Run
./configure
. For a full list of configuration options, use./configure --help
. - Run
make
- Optionally, run
make install
. The installation prefix can be changed via./configure --prefix=...
- fedora 系统 需要安装 openmpi 和 openmpi-devel rpm 包来进行配置环境并记得在 .bash_profile 中进行配置环境变量;具体环境变量配置如下列截图所示:
使用说明:
运行 IOR 有两种方法:
带参数的命令行 - 可执行文件后跟命令行选项:$ ./ior -w -r -o filename这将对文件“filename”执行写入和读取。
带脚本的命令行 - 命令行上的任何参数都将建立测试运行的默认值,但脚本可以与此结合使用,以在代码执行期间改变特定的测试。仅使用脚本之前的参数$ ./ior -W -f script 这默认“脚本”中的所有测试都使用写入数据检查。
IOR 入门
IOR使用以下参数顺序写入数据:
blockSize( -b) transferSize( -t) segmentCount( -s) numTasks( -n)
最好用图表来说明:
这四个参数是您开始使用 IOR 所需的全部。然而,单纯地运行 IOR 通常会给出令人失望的结果。例如,如果我们运行四节点 IOR 测试,总共写入16GiB:
$ mpirun -n 64 ./ior -t 1m -b 16m -s 16 ... access bw(MiB/s) block(KiB) xfer(KiB) open(s) wr/rd(s) close(s) total(s) iter ------ --------- ---------- --------- -------- -------- -------- -------- ---- write 427.36 16384 1024.00 0.107961 38.34 32.48 38.34 2 read 239.08 16384 1024.00 0.005789 68.53 65.53 68.53 2 remove - - - - - - 0.534400 2
我们每秒只能从 Lustre 文件系统中获取几百兆字节的数据,而 Lustre 文件系统的容量本应更大。
-F
使用( ) 选项从写入单个共享文件切换为每个进程一个文件,这 filePerProcess=1
会显着改变性能:
$ mpirun -n 64 ./ior -t 1m -b 16m -s 16 -F ... access bw(MiB/s) block(KiB) xfer(KiB) open(s) wr/rd(s) close(s) total(s) iter ------ --------- ---------- --------- -------- -------- -------- -------- ---- write 33645 16384 1024.00 0.007693 0.486249 0.195494 0.486972 1 read 149473 16384 1024.00 0.004936 0.108627 0.016479 0.109612 1 remove - - - - - - 6.08 1
这在很大程度上是因为让每个 MPI 进程处理自己的文件可以消除因文件锁定而产生的任何争用。
然而,我们的简单测试和每个进程文件测试之间的性能差异有点极端。事实上,在 Lustre 上实现 146 GB/秒读取速率的唯一方法是四个计算节点中的每一个都具有超过 45 GB/秒的到 Lustre 的网络带宽,即每个计算和存储上都有 400 Gbit 链路节点。
页面缓存对基准测试的影响
真正发生的情况是,IOR 读取的数据实际上并不是来自 Lustre;而是来自 Lustre。相反,文件的内容已经被缓存,并且 IOR 能够直接从每个计算节点的 DRAM 中读取它们。由于 Linux(和 Lustre)使用回写缓存来缓冲 I/O,数据最终在 IOR 的写入阶段被缓存,因此 IOR 不是直接向 Lustre 写入和读取数据,实际上主要是在说话到每个计算节点上的内存。
更具体地说,虽然每个 IOR 进程都认为自己正在写入 Lustre 上的文件,然后从 Lustre 读回该文件的内容,但实际上它是
- 将数据写入内存中缓存的文件副本。如果在此写入之前内存中没有缓存文件的副本,则正在修改的部分将首先加载到内存中。
- 内存中文件的那些部分(称为“页面”)现在与 Lustre 上的内容不同,被标记为“脏”
- write() 调用完成并且 IOR 继续,即使写入的数据尚未提交给 Lustre
- 独立于 IOR,操作系统内核不断扫描文件缓存,查找已在内存中更新但未在 Lustre 上更新的文件(“脏页”),然后将缓存的修改提交到 Lustre
- 脏页被声明为非脏页,因为它们现在与磁盘上的内容同步,但它们仍保留在内存中
然后,当 IOR 的读取阶段在写入阶段之后时,IOR 能够从内存中检索文件的内容,而不必通过网络与 Lustre 进行通信。
有多种方法可以测量底层 Lustre 文件系统的读取性能。最粗略的方法是简单地写入比总页缓存容纳的数据更多的数据,以便在写入阶段完成时,文件的开头已经从缓存中逐出。例如,增加段数 ( -s
) 以写入更多数据,可以非常清楚地揭示测试系统上节点页面缓存的运行点:
然而,这可能会导致在具有大量节点内存的系统上运行 IOR 需要很长时间。更好的选择是让每个节点上的 MPI 进程只读取它们未写入的数据。例如,在每节点 4 个进程的测试中,将 MPI 进程到块的映射移动 4 个,使每个节点 N 读取节点 N-1 写入的数据。
由于页面缓存不在计算节点之间共享,因此以这种方式转移任务可确保每个 MPI 进程正在读取它未写入的数据。
IOR 提供了-C
选项 ( reorderTasks
) 来执行此操作,它强制每个 MPI 进程读取其相邻节点写入的数据。使用此选项运行 IOR 可提供更可靠的读取性能:
$ mpirun -n 64 ./ior -t 1m -b 16m -s 16 -F -C ... access bw(MiB/s) block(KiB) xfer(KiB) open(s) wr/rd(s) close(s) total(s) iter ------ --------- ---------- --------- -------- -------- -------- -------- ---- write 41326 16384 1024.00 0.005756 0.395859 0.095360 0.396453 0 read 3310.00 16384 1024.00 0.011786 4.95 4.20 4.95 1 remove - - - - - - 0.237291 1
但现在看起来很明显,写入性能也高得离谱。同样,这是由于页面缓存,当写入已提交到内存而不是底层 Lustre 文件系统时,页面缓存会向 IOR 发出写入完成的信号。
为了解决页面缓存对写入性能的影响,我们可以在所有 write() 返回后立即发出 fsync() 调用,以强制我们刚刚写入的脏页刷新到 Lustre。包括 fsync() 完成所需的时间可以让我们衡量数据写入页面缓存以及页面缓存写回 Lustre 所需的时间。
IOR 提供了另一个方便的选项-e
(fsync)来做到这一点。并且,再次使用此选项会极大地改变我们的性能测量:
$ mpirun -n 64 ./ior -t 1m -b 16m -s 16 -F -C -e ... access bw(MiB/s) block(KiB) xfer(KiB) open(s) wr/rd(s) close(s) total(s) iter ------ --------- ---------- --------- -------- -------- -------- -------- ---- write 2937.89 16384 1024.00 0.011841 5.56 4.93 5.58 0 read 2712.55 16384 1024.00 0.005214 6.04 5.08 6.04 3 remove - - - - - - 0.037706 0
我们终于对我们的文件系统有了可信的带宽测量。
击败页面缓存
由于 IOR 是专门为 I/O 基准测试而设计的,因此它提供了这些选项,可以尽可能轻松地确保您实际测量的是文件系统的性能,而不是计算节点内存的性能。话虽这么说,它生成的 I/O 模式旨在展示峰值性能,而不是反映实际应用程序可能尝试执行的操作,因此,在很多情况下,使用 IOR 测量 I/O 性能并不适用。永远是最好的选择。有几种方法可以让我们变得更聪明,并在更一般的意义上击败页面缓存,以获得有意义的性能数据。
在测量写入性能时,绕过页面缓存实际上非常简单;打开带有O_DIRECT
直接到磁盘标志的文件。此外,fsync()
调用可以插入到应用程序中,就像使用 IOR-e
选项所做的那样。
测量读取性能要困难得多。如果您有幸在测试系统上拥有 root 访问权限,则可以通过执行以下操作强制 Linux 内核清空其页面缓存
# echo 1 > /proc/sys/vm/drop_caches
事实上,在运行任何基准测试(例如 Linpack)之前,这通常是一个很好的做法,因为它可以确保当基准应用程序开始分配内存供自己使用时,内核尝试逐出页面时不会损失性能。
不幸的是,我们中的许多人都没有系统root权限,所以我们必须变得更加聪明。事实证明,有一种方法可以向内核传递一个提示:页面缓存中不再需要某个文件:
#define _XOPEN_SOURCE 600 #include <unistd.h> #include <fcntl.h> int main(int argc, char *argv[]) { int fd; fd = open(argv[1], O_RDONLY); fdatasync(fd); posix_fadvise(fd, 0,0,POSIX_FADV_DONTNEED); close(fd); return 0; }
使用传递 POSIX_FADV_DONTNEED 的效果posix_fadvise()
通常是属于该文件的所有页面都被从 Linux 中的页面缓存中逐出。然而,这只是一个提示——而不是保证——并且内核异步逐出这些页面,因此页面可能需要一两秒才能真正离开页面缓存。幸运的是,Linux 还提供了一种方法来探测文件中的页面以查看它们是否驻留在内存中。
最后,限制可用于页面缓存的内存量通常是最简单的。由于应用程序内存始终优先于缓存内存,因此简单地在节点上分配大部分内存将强制驱逐大部分缓存页面。新版本的 IOR 提供了 memoryPerNode 选项来实现这一点,其效果正如人们所期望的那样:
上图显示了总 DRAM 为 128 GiB 的单个节点的测量带宽。每个 x 标签上的第一个百分比是基准测试保留作为应用程序内存的 128 GiB 的量,第二个百分比是总写入量。例如,“50%/150%”数据点对应于为应用程序分配的节点内存 (64 GiB) 的 50%,以及总共读取的 192 GiB 数据。
该基准测试在单个旋转磁盘上运行,该磁盘的速度不能超过 130 MB/秒,因此显示高于此性能的条件得益于缓存提供的某些页面。考虑到异常高性能测量是在相对于正在读取的数据量有足够的内存可缓存时获得的,这是完全有道理的。
六、dd测试工具 (磁盘IO测试-针对于顺序IO)
使用 dd 来测试硬盘读写速度,dd 只能提供一个大概的测试结果,而且是连续IO不是随机IO,理论上文件规模越大,测试结果就越精准。
使用场景,适用在单节点进行测试。
dd 工具使用:
dd 也是我们经常使用到的磁盘测试工具,Linux服务器装好系统之后,想要知道硬盘的读写是否能满足服务的需要,如果不满足硬盘的IO就是服务的一个瓶颈。我们可以使用dd命令简单进行测试,更为专业的测试可以使用上面描述的fio 工具:
time有计时作用,dd用于复制,从if读出,写到of。if=/dev/zero不产生IO,因此可以用来测试纯写速度。同理of=/dev/null不产生IO,可以用来测试纯读速度。bs是每次读或写的大小,即一个块的大小,count是读写块的数量。
dd测试纯写速度:
[root@docker sda]# time dd if=/dev/zero of=/mnt/sda/ddout bs=8k count=1000000 1000000+0 records in 1000000+0 records out 8192000000 bytes (8.2 GB, 7.6 GiB) copied, 43.1081 s, 190 MB/s real 0m43.110s user 0m0.207s sys 0m3.914s
dd测试纯读速度:
[root@docker sda]# time dd if=/mnt/sda/ddout of=/dev/null bs=8k count=1000000 1000000+0 records in 1000000+0 records out 8192000000 bytes (8.2 GB, 7.6 GiB) copied, 1.30322 s, 6.3 GB/s real 0m1.306s user 0m0.199s sys 0m1.102s
dd 测试读写速度,就是读当前磁盘文件,再写入当前磁盘之中。一定程度上,复制量越大,读写的时间越长,统计的结果越准。但是测试结果信息量较少,只能作为参考量,更多读写模式和测试信息:可以使用dd 命令参数来配置:
使用conv, iflag, oflag 三个变量可以配置dd 命令的复制模块式,读取模式和写入模式;
conv 关键symbol:
fdatasync physically write output file data before finishing fsync likewise, but also write metadata
iflag, oflag 关键symbol:
dsync use synchronized I/O for data sync likewise, but also for metadata direct use direct I/O for data
dd 命令绕过系统cache:
如果要规避掉文件系统cache,直接读写,不使用buffer cache,需做这样的设置 iflag=direct,nonblock oflag=direct,nonblock
dd 命令三种经典使用方法:
dd if=/dev/zero of=test bs=64k count=16k 是不准确的,可能有数据存在内核缓存中,没有同步到磁盘上。对于关键数据应该加上fsync标识,防止关键数据丢失; dd if=/dev/zero of=test bs=64k count=16k conv=fsync 较为稳妥,但是时间用时较长,他在dd结束前会写数据和文件元数据到磁盘; dd if=/dev/zero of=test bs=64k count=4k oflag=dsync or sync 每写一次就写一次磁盘,在实际操作中,可以听到磁盘响声,用时较长;
SSD 性能测试:
PCIe-SSD Optane: dd if=/dev/urandom of=./optane.bin bs=256k count=102400 (顺序写 25GB的随机数据) M.2-STAT-SSD: dd if=/dev/urandom of=./m2sata.bin bs=256k count=102400 (顺序写 25GB的随机数据) M.2-NVMe-SSD: dd if=/dev/urandom of=./m2nvme.bin bs=256k count=102400 (顺序写 25GB的随机数据) HDD: dd if=/dev/urandom of=./sata.bin bs=256k count=102400 (顺序写 25GB的随机数据)
七、Iperf (网络测试,测试分布式存储系统中网络的实际带宽,主要是对tcp/udp协议的测试)
Iperf 是一个网络性能测试工具。IPerf可以测试最大的TCP和UDP带宽性能。Iperf具有多种参数和特性,可以根据需要调整。IPerf可以报告带宽。延迟抖动和数据包丢失。iperf3是一个网络速度测试工具,支持IPv4与IPv6,支持TCP、UDP、SCTP传输协议,可在Windows、Mac OS X、Linux、FreeBSD等各种平台使用,是一个简单又实用的小工具。本文介绍安装、使用iperf3 网速测试工具。
在分布式文件系统开发和测试过程中,我们经常需要测试真实的网络带宽,来进行估测分布式系统的传输性能,所以我们要对现有的网络进行测试;Iperf 是一个网络性能测试工具。IPerf可以测试最大的TCP和UDP带宽性能。Iperf具有多种参数和特性,可以根据需要调整。IPerf可以报告带宽。延迟抖动和数据包丢失。
下面就对iperf 软件的功能和用法进行简单的介绍:
官方网站:
https://iperf.fr/ (iperf 3) http://sourceforge.net/projects/iperf2 http://github.com/esnet/iperf 具体的两个不同,网站进行了解;
在ubuntu或者fedora 中,可以使用 apt或者yum 来进行搜索安装;
具体用法:
具体的使用 可以使用 man iperf 命令来进行安装;
常用测试选项:(iperf2 和 iperf3 稍有不同)
- -i 设置iperf输出结果的时间间隔
- -m 在结果中显示TCP的MSS大小
- -u 使用UDP协议
- -M 设置TCP的MSS大小
- -s 以server模式运行
- -c 以client模式运行
- -t 设置iperf测试时间
- -n 设置iperf测试时发送的数据量,与‘-t’参数二选一
- -P 并行运行的线程数,默认为1
- -b 设置测试时的发送带宽
- -w TCP协议时设置TCP window的大小,UDP协议时设置接收缓冲大小
测试例子:
- root@buaa-3:~# iperf -u -s -p 80
- 测试 80端口 udp 接收情况;
- [root@docker ~]# iperf -c 192.168.10.14 -u -p 80 -e -i 1
- 连接 80端口进行测试 并以1秒为间隔输出;
- iperf 既可以用于网络带宽测试也可以用来进行端口测试。
iperf 3 使用说明:
➜ ~ iperf3 -h Usage: iperf3 [-s|-c host] [options] iperf3 [-h|--help] [-v|--version] Server or Client: -p, --port # server port to listen on/connect to -f, --format [kmgtKMGT] format to report: Kbits, Mbits, Gbits, Tbits -i, --interval # seconds between periodic throughput reports -F, --file name xmit/recv the specified file -B, --bind <host> bind to the interface associated with the address <host> -V, --verbose more detailed output -J, --json output in JSON format --logfile f send output to a log file --forceflush force flushing output at every interval -d, --debug emit debugging output -v, --version show version information and quit -h, --help show this message and quit Server specific: -s, --server run in server mode -D, --daemon run the server as a daemon -I, --pidfile file write PID file -1, --one-off handle one client connection then exit --rsa-private-key-path path to the RSA private key used to decrypt authentication credentials --authorized-users-path path to the configuration file containing user credentials Client specific: -c, --client <host> run in client mode, connecting to <host> -u, --udp use UDP rather than TCP --connect-timeout # timeout for control connection setup (ms) -b, --bitrate #[KMG][/#] target bitrate in bits/sec (0 for unlimited) (default 1 Mbit/sec for UDP, unlimited for TCP) (optional slash and packet count for burst mode) --pacing-timer #[KMG] set the timing for pacing, in microseconds (default 1000) -t, --time # time in seconds to transmit for (default 10 secs) -n, --bytes #[KMG] number of bytes to transmit (instead of -t) -k, --blockcount #[KMG] number of blocks (packets) to transmit (instead of -t or -n) -l, --length #[KMG] length of buffer to read or write (default 128 KB for TCP, dynamic or 1460 for UDP) --cport <port> bind to a specific client port (TCP and UDP, default: ephemeral port) -P, --parallel # number of parallel client streams to run -R, --reverse run in reverse mode (server sends, client receives) --bidir run in bidirectional mode. Client and server send and receive data. -w, --window #[KMG] set window size / socket buffer size -M, --set-mss # set TCP/SCTP maximum segment size (MTU - 40 bytes) -N, --no-delay set TCP/SCTP no delay, disabling Nagle's Algorithm -4, --version4 only use IPv4 -6, --version6 only use IPv6 -S, --tos N set the IP type of service, 0-255. The usual prefixes for octal and hex can be used, i.e. 52, 064 and 0x34 all specify the same value. --dscp N or --dscp val set the IP dscp value, either 0-63 or symbolic. Numeric values can be specified in decimal, octal and hex (see --tos above). -Z, --zerocopy use a 'zero copy' method of sending data -O, --omit N omit the first n seconds -T, --title str prefix every output line with this string --extra-data str data string to include in client and server JSON --get-server-output get results from server --udp-counters-64bit use 64-bit counters in UDP test packets --repeating-payload use repeating pattern in payload, instead of randomized payload (like in iperf2) --username username for authentication --rsa-public-key-path path to the RSA public key used to encrypt authentication credentials [KMG] indicates options that support a K/M/G suffix for kilo-, mega-, or giga-
八、netperf (首先使用指定端口交换控制信息,再开另外的端口进行对tcp的stream,rr,crr和udp的stream,rr等应用模式进行测试)
netperf是惠普公司开源的一款针对网络性能的测试工具,主要基于TCP或UDP的传输。根据应用的不同,可以进行批量数据传输(bulk data transfer)模式和请求/应答(request/reponse)模式的性能测试。
netperf以Client/Server方式工作。Server端是netserver,用来侦听来自client端的连接,Client端是netperf,用来向Server发起网络测试。在Client与Server之间,首先建立一个控制连接,传递有关测试配置的信息,以及测试的结果;在控制连接建立并传递了测试配置信息以后,Client与Server之间会再建立一个测试连接,来回传递特殊的流量模式,用来测试网络的性能。
netperf测试结果反映了一个系统能够以多快的速度向另外一个系统发送数据,以及另外一个系统能够以多块的速度接收数据。
官方网址:
https://hewlettpackard.github.io/netperf/ https://github.com/HewlettPackard/netperf
下载最新版本:(2019-8-14)
curl -L https://codeload.github.com/HewlettPackard/netperf/zip/netperf-2.7.0 -o netperf.zip cd netperf ./configure make cd src
找到可执行的二进制文件,即可以使用了。
网络测试的五项指标:
- 可用性(availability):可使用ping 命令测试网络是否通畅;
- 响应时间(response time):ping 命令echo request/reply 一次往返所花费的时间;
- 网络利用率(network utilization):指的是网络使用时间和空闲时间的比例;
- 网络吞吐量(network throughput):在网络中两个节点之间,提供给网络应用的剩余带宽,测试网络吞吐的时候,需要在一天的不同时刻来进行测量;
- 网络带宽容量(network bandwidth capacity):与吞吐不同,网络带宽容量指的是在网络两个节点之间的最大可用带宽。该值是由网络设备本身的能力决定的。
收集网络性能数据的方式:
- 使用snmp协议直接到网络设备中获取;
- 侦听相关的网络性能数据,典型的工具为tcpdump;
- 自行产生相应的测试数据,使用netperf工具等;
TCP网络性能测试:
由于tcp协议能够提供端到端的可靠的传输,被大量网络应用程序使用。但是建立可靠的连接需要付出一定的代价,如维护连接,控制数据有序传递等都会消耗一定的带宽。
netperf提供的三种tcp模式:
- 单个tcp连接,批量传输大量数据;
- 单个tcp连接,client请求/server 应答模式;
- 多个tcp连接,每个连接中一对请求应答 transaction 方式;
UDP网络性能测试:
udp不能保持可靠传输,所以使用UDP不能保证传输的可靠性,所以UDP应用需要自行跟踪每个发出的分组,并重发丢失的分组。
netperf 提供两种udp流量测试模式:
- 从client 到 server 的单向批量传输;
- 请求应答模式
由于UDP传输的不可靠性,使用netperf时,要确保发送缓冲区不大于接收缓冲区,否则数据会丢失。
软件使用:
- 启动netserver 使用特定端口:
- -D 表示以非deamon 进程运行
- -4 表示测试的为ipv4网络;
- -p 表示使用特定端口;
启用netperf 软件:
- netperf 软件特定格式:netperf [global options] -- [test-specific options]
- netperf命令行参数可以分为两大类:全局命令行参数和测试相关的局部参数,两者之间通过--分隔
常用命令行参数:
- -H host :指定远端运行netserver的server IP地址。
- -l testlen:指定测试的时间长度(秒)
- -t testname:指定进行的测试类型,包括TCP_STREAM,UDP_STREAM,TCP_RR,TCP_CRR,UDP_RR
- 精品文章推荐阅读:
- 掌握GDB调试工具,轻松排除bug
- 深入理解C++内存管理:指针、引用和内存分配
- 打破常规,Linux内核新的数据结构上场maple tree
- 深入挖掘Linux内核源码:揭秘其惊人的架构和设计
- 从零开始学习 Linux 内核套接字:掌握网络编程的必备技能
- 解密Linux内核神器:内存屏障的秘密功效与应用方法
- Linux内核文件系统:比万物之神还要强大的存储魔法!
- 内存分配不再神秘:深入剖析malloc函数实现原理与机制
- 探索网络通信核心技术,手写TCP/IP用户态协议栈,让性能飙升起来!
- 万字总结简化跨平台编译利器CMake,从入门到项目实战演练!