性能是评估一个文件系统的最为关键的维度,根据文件系统在不同场景下的性能表现,可以判断文件系统是否适合特定的应用场景,并为系统性能调优提供依据。
当我们使用一个文件系统时(例如Ext4),我们怎么知道这个文件系统是否可靠?它的性能与稳定性如何?这个文件系统的性能瓶颈在哪里?以及如何才能发挥出文件系统的最佳性能?
下文即将介绍的iozone
工具将帮助你测试这一切。
IOzone是一个文件系统基准测试工具。该基准测试生成并测量各种文件操作。
Iozone已经被移植到许多机器上,并在许多操作系统下运行。
基准测试针对以下操作测试文件I/O性能:
IOzone Filesystem Benchmark 官网
不同平台iozone工具安装方法:
iozone
首先去官网下载iozone源码(Latest或者stable版本都可以)
笔者下载的是 iozone3_494.tgz
修改makefile
CC = aarch64-linux-gnu-gcc # 修改为交叉编译器
C89 = c89
GCC = aarch64-linux-gnu-gcc # 修改为交叉编译器
......
$ cd iozone3_494/src/current
$ chmod 755 * #给文件增加读写权限
$ make clean # 清除之前编译结果
$ make linux-arm # 一定要指定平台类型,arm64也可以指定为 linux-arm
编译成功后将iozone3_494/src/current/iozone
二进制文件拷贝到开发板即可。
仅涵盖大部分选项,更全面的选项说明请执行iozone -h
。
OPTIONS | 说明 | 备注 |
---|---|---|
-a | 全自动测试模式。记录大小从4k到16M,文件大小从64k到512M | |
-A | 这个版本的自动模式提供了更多的覆盖率,但消耗了大量的时间。当文件大小大于或等于32 MB时,-a选项会自动停止使用小于64k的传输大小。这节省了时间。-A选项告诉Iozone用户愿意等待,即使文件非常大,也希望对小传输进行密集覆盖。注意:这个选项在Iozone 3.61版本中已被弃用。请使用-az -i 0 -i 1代替。 | flash编程的最小单位,一般=pagesize |
-b filename | Iozone 将创建一个二进制文件格式的文件filename,并以 Excel 兼容的方式输出结果 | |
-B | 使用mmap()文件。这使得所有要测量的临时文件都可以通过mmap()接口创建和访问。有些应用程序喜欢将文件视为内存数组。这些应用程序对文件进行mmap()操作,然后通过加载和存储访问数组来执行文件I/O操作。 | |
-c | 在计时计算中包含close()。只有当你怀疑close()在当前测试的操作系统中有问题时,这才有用。它对于NFS版本3的测试也很有用,可以帮助确定nfs3_commit是否正常工作。 | |
-C | 在吞吐量测试中显示每个子进程传输的字节数。如果你的操作系统在文件I/O或进程管理中有任何饥饿问题,这很有用。 | |
-d # | 在屏障外的微秒延迟。在吞吐量测试期间,在开始测试之前,所有线程或进程都被强制设置为屏障。通常,所有的线程或进程都会在同一时刻被释放。该选项允许在释放每个进程或线程之间延迟指定的时间(以微秒为单位)。 | |
-D | 在 mmap 文件上使用 msync(MS_ASYNC)。 这告诉操作系统需要将mmap空间中的所有数据异步写入磁盘 | |
-e | 在计时计算中包含flush (fsync,fflush) | |
-E | 用于选择扩展测试。使用pread接口 | 仅在某些平台上可用。 |
-f filename | 用于指定被测试临时文件的文件名。在使用unmount选项时,这很有用。当在测试之间使用unmount进行测试时,测试中的临时文件必须位于可以卸载的目录中。无法卸载当前工作目录,因为Iozone进程正在这个目录中运行 | |
-F filename filename filename … | 指定吞吐量测试中使用的每个临时文件名。名称的数量应该等于指定的进程或线程的数量。 | |
-g # | 设置自动模式下的最大文件大小(以KB为单位)。 | |
-G | 在mmap文件上使用msync(MS_SYNC)。这告诉操作系统,mmap空间中的所有数据都需要同步写入磁盘 | |
-H | 将 POSIX 异步 I/O 与 # 异步操作一起使用。 Iozone 将使用 POSIX 异步 I/O,将异步缓冲区中的 bcopy 返回到应用程序缓冲区中。 某些版本的 MSC NASTRAN 以这种方式执行 I/O。 应用程序使用此技术,以便异步 I/O 可以在库中执行,并且不需要更改应用程序内部模型。 | |
-i # | 用于指定要运行的测试。(0=write/rewrite, 1=read/re-read, 2=random-read/write5=stride-read, 6=fwrite/re-fwrite, 7=fread/Re-fread,9=pwrite/Re-pwrite, 10=pread/Re- preread, 11=pwritev/Re-pwritev, 12=preadv/Re-preadv)。 | 任何测试都需要指定0,以便后面的测试都有一个要测量的文件。-i # -i # -i #也被支持,所以同时可以选择多个测试。 |
-I | 对所有文件操作使用 DIRECT I/O。 告诉文件系统所有操作都绕过缓冲区缓存并直接转到磁盘。 这还将在 VxFS 上使用 VX_DIRECT,在 Linux 上使用 O_DIRECT,在 Solaris 上使用 directio()。 | — |
-j # | 将文件访问的步幅设置为(# * 记录大小)。 步幅读取测试将以该步幅读取记录。 | — |
-J #(单位ms) | 在每次I/O操作之前执行这个数毫秒的计算延迟。其他控制计算延迟的选项请参见-X和-Y。 | — |
-K # | 使用POSIX async I/O(无bcopy)和# async操作。Iozone将使用POSIX异步I/O,不会执行任何额外的bcopy操作。Iozone使用的缓冲区将直接传递给异步I/O系统调用。 | — |
-K | 在正常测试期间生成一些随机访问 | — |
-I # | 设置要运行的进程数的下限。当运行吞吐量测试时,此选项允许用户指定要启动的进程或线程的最小数量。 | 这个选项应该和-u选项一起使用。 |
-L # | 将处理器缓存行大小设置为value(以字节为单位)。告诉Iozone处理器缓存行大小。 | 这是内部使用的,以帮助加速测试。 |
-m | 告诉Iozone在内部使用多个缓冲区。有些应用程序会一遍又一遍地读入同一个缓冲区。另一些则是buffer数组。此选项允许模拟两种类型的应用程序。Iozone的默认行为是重用内部缓冲区。此选项允许覆盖默认值并使用多个内部缓冲区。 | — |
-M | Iozone将调用uname(),并将字符串放入输出文件中。 | — |
-n # | 设置自动模式下的最小文件大小(以KB为单位)。 | — |
-N | 以微秒为单位报告每个操作的结果。 | — |
-o | 写入同步写入磁盘(O_SYNC)。Iozone会用O_SYNC标志打开文件。这将强制所有对文件的写入在返回基准测试之前全部写入磁盘。 | — |
-O | Give results in operations per second. | — |
-p | 这将在每次文件操作之前清除处理器缓存。Iozone将分配另一个内部缓冲区,该缓冲区对齐到相同的处理器缓存边界,大小与处理器缓存匹配。它将在开始每个测试之前填充这个备用缓冲区。这将清除处理器缓存,并允许查看内存子系统,而不会因为处理器缓存而加速。 | — |
-P # | 将进程/线程绑定到处理器,从这个cpu #开始。仅在某些平台上可用。第一个子进程或线程将在指定的处理器上开始。未来的进程或线程将被放置在下一个处理器上。一旦超过了cpu的总数,未来的进程或线程将以轮询方式放置。 | — |
-q # | 设置自动模式下的最大记录大小(以KB为单位)。也可以指定-q #k(以KB为单位的大小)或-q #m(以MB为单位的大小)或-q #g(以GB为单位的大小)。参见-y设置最小记录大小。 | — |
-Q | 创建偏移/延迟文件。Iozone将创建延迟与偏移量数据文件,可以使用图形包导入并绘制这些文件。这对于发现某些偏移量是否具有非常高的延迟很有用。比如UFS分配第一个间接块的位置。从数据可以看出,对于具有该选项的基于区间的文件系统,区间分配的影响。 | — |
-r # | 用于指定要测试的记录大小,以Kbytes为单位。也可以指定-r #k(以KB为单位的大小)或-r #m(以MB为单位的大小)或-r #g(以GB为单位的大小)。 | — |
-R | 生成 Excel 报告。 Iozone 将生成一个 Excel 兼容报告以标准输出。 该文件可以用 Microsoft Excel(空格分隔)导入并用于创建文件系统性能图。 | 注意:3D 图形是面向列的。 绘图时需要选择此项,因为 Excel 中的默认值是面向行的数据。 |
-s # | 用于指定要测试文件大小,以Kbytes为单位。也可以指定-r #k(以KB为单位的大小)或-r #m(以MB为单位的大小)或-r #g(以GB为单位的大小)。 | — |
-S # | 将处理器缓存大小设置为value(以Kbytes为单位)。这会告诉Iozone处理器缓存的大小。它在内部用于缓冲区对齐和清除功能。 | — |
-t # | 以吞吐量模式运行Iozone。该选项允许用户指定在测量期间有多少线程或进程处于活动状态。 | — |
-T | 使用POSIX pthreads进行吞吐量测试。在具有POSIX线程的平台上可用 | — |
-u # | 设置要运行的进程数的上限。当运行吞吐量测试时,此选项允许用户指定要启动的最大进程或线程数。 | 这个选项应该和-l选项一起使用。 |
-U mountpoint | 在测试之间卸载和重新装载的装载点。在开始每次测试之前,Iozone将卸载并重新安装该挂载点。这保证了缓冲区缓存不包含任何被测试的文件。 | — |
-v | 显示Iozone的版本信息。 | — |
-V # | 指定一个模式,该模式将写入临时文件,并在每个读取测试中验证其准确性。 | — |
-w | 使用完毕后不要取消链接临时文件。 将它们留在文件系统中。 | — |
-W | 读取或写入时锁定文件。 | — |
-x | 关闭石墙。石墙是一种用于Iozone内部的技术。它在吞吐量测试期间使用。代码启动所有线程或进程,然后在barrier上停止它们。一旦他们都准备好开始,然后他们都在同一时间释放。当任何线程或进程完成它们的工作时,整个测试将终止,并根据到此为止完成的总I/O计算吞吐量。这确保了在所有进程或线程并行运行时进行整个测量。这个flag允许一个人关闭石墙,看看会发生什么。 | — |
-X filename | 使用此文件写入遥测信息。 该文件包含三元组信息:字节偏移量、传输大小、计算延迟(以毫秒为单位)。 如果对感兴趣的应用程序进行了系统调用跟踪,则此选项很有用。 这允许 Iozone 复制此特定应用程序生成的 I/O 操作并提供此文件行为的基准测试结果。 (如果第 1 列包含 # 则该行是注释) | — |
-y # | 设置自动模式下的最小记录大小(以KB为单位)。也可以指定- y# k(以KB为单位的大小)或- y# m(以MB为单位的大小)或- y# g(以GB为单位的大小)。 | 参见-q设置最大记录大小。 |
-Y filename | 使用这个文件读取遥测信息。该文件包含三个信息:字节偏移量、传输大小、以毫秒为单位的计算延迟。如果对感兴趣的应用程序进行了系统调用跟踪,则此选项很有用。这允许Iozone复制特定应用程序生成的I/O操作,并为该文件提供基准测试结果 | |
的行为。(如果列1包含#,则该行为注释) | — | |
-z | 与 -a 结合使用以测试所有可能的记录大小。 当在全自动模式下使用时,Iozone 通常会忽略对非常大的文件的小记录大小的测试。 此选项强制 Iozone 在自动测试中也包括小记录大小。 | — |
-Z | 启用混合mmap I/O和文件I/O。 | — |
-+m filename | 该文件用于获取集群测试客户端的配置信息。每个客户端对应一个文件。每行有三个字段。字段由空格分隔。第0列中的#符号是注释行。第一个字段是客户端的名称。第二个字段是客户端上的路径,表示Iozone将要执行的工作目录。第三个字段是客户端可执行文件Iozone的路径。要使用此选项,必须能够在客户端上执行命令,而不需要询问密码。Iozone将通过使用“rsh”开始远程执行。 | — |
-+n | 没有选择重新测试。使用它可以防止重新测试运行。 | — |
-+N | 在顺序写入测试之前,不会截断或删除先前的测试文件。 只有在前面的命令中使用 -w 将测试文件留在原处以供重用后才有用。 此标志的用途有限,当单个重新测试不够时,或者在不截断或删除文件的情况下轻松控制顺序写入重新测试的时间。 | — |
-+u | 开启CPU利用率模式。 | — |
-+d | 开启诊断模式。在这种模式下,每个字节都被验证。如果怀疑是I/O子系统有问题,这很方便 | — |
-+p | 设置执行随机读取测试的线程/进程的百分比。 | 仅在吞吐量模式和多于一个进程/线程时有效。 |
-+r | 对所有I/O测试启用O_RSYNC和O_SYNC。 | — |
-+t | 开启网络性能测试。要求——+ m | — |
-+A | 启用madvise。0 =正常,1=随机,2=顺序,3=不需要,4=将需要。用于激活mmap()文件I/O的选项。看:- B | — |
-i #
用于指定测试类型,我们可以自由组合测试类型,但是-i 0
是必选的,这也是为后续测试提供测试文件。
测试类型 | 说明 | 备注 |
---|---|---|
write | 这个测试测量写入新文件的性能。在写入新文件时,不仅需要存储数据,还需要记录数据在存储介质上的位置。这种开销称为“元数据”,它包括目录信息、空间分配和与文件相关的任何其他数据,但这些数据不是文件中包含的数据的一部分。由于这些开销信息,初始写性能低于重写文件的性能是正常的 | — |
rewrite | 这个测试测量了写入一个已经存在的文件的性能。在写入已经存在的文件时,所需的工作较少,因为元数据已经存在。重写性能高于写新文件的性能是正常现象。 | — |
Read | 这个测试测量读取现有文件的性能。 | — |
Re-Read | 这个测试测量读取最近读取的文件的性能。性能提高是正常的,因为操作系统通常会为最近读取的文件维护数据缓存。该缓存可用于满足读取要求并提高性能。。 | — |
Random Read | 该测试测量读取文件的性能,访问文件中的随机位置。 系统在此类活动下的性能会受到多种因素的影响,例如:操作系统缓存的大小、磁盘数量、寻道延迟等。 | — |
Random Write | 该测试测量写入文件的性能,访问文件中的随机位置。 同样,系统在此类活动下的性能可能会受到多种因素的影响,例如:操作系统缓存的大小、磁盘数量、寻道延迟等。 | — |
Random Mix | 该测试测量读取和写入文件的性能,访问文件中的随机位置。 同样,系统在此类活动下的性能可能会受到多种因素的影响,例如:操作系统缓存的大小、磁盘数量、寻道延迟等。 此测试仅在吞吐量模式下可用。 每个线程/进程运行读取或写入测试。 读/写的分配是在循环的基础上完成的。 正确操作需要不止一个线程/进程。 | — |
Backwards Read | 这个测试测试了向后读取文件的性能。这可能看起来是一种奇怪的读取文件的方式,但实际上有些应用程序会这样做。MSC Nastran是一个向后读取文件的应用程序的示例。使用MSC Nastran,这些文件非常大(大小为Gbytes到Tbytes)。尽管许多操作系统都具有特殊的特性,使它们能够更快地向前读取文件,但很少有操作系统能够检测并增强向后读取文件的性能。 | — |
Record Rewrite | 这个测试测量写入和重写文件中特定位置的性能。这个热点可以有非常有趣的行为。如果spot的大小足够小,可以放入CPU的数据缓存,那么性能是非常高的。如果内存块的大小比CPU数据缓存大,但仍然可以放入TLB,那么性能会有所不同。如果内存块的大小大于CPU的数据缓存和TLB,但仍然可以放在操作系统的缓存中,那么可以获得另一种级别的性能;如果内存块的大小大于操作系统的缓存,那么可以获得另一种级别的性能。 | — |
Strided Read | 这个测试测量了以跨步访问行为读取文件的性能。例如:在偏移量0处读取长度为4 Kbytes的数据,然后查找长度为200 Kbytes的数据,然后读取长度为4 Kbytes的数据,然后查找长度为200 Kbytes的数据,以此类推。这里的模式是读取4 kb,然后查找200 kb,并重复该模式。这也是应用程序的典型行为在文件中包含数据结构,并且正在访问该数据结构的特定区域。大多数操作系统不会检测这种行为,也不会实现任何技术来提高这种访问行为下的性能。这种访问行为有时也会产生有趣的性能异常。例如,如果应用程序的stride导致条带文件系统中的特定磁盘成为瓶颈。 | — |
Fwrite | 这个测试测试了使用库函数fwrite()写文件的性能。这是一个库例程,执行缓冲写操作。缓冲区在用户的地址空间内。如果应用程序要写入非常小的传输,那么fwrite()的缓冲和阻塞I/O功能可以通过减少实际操作系统调用的数量和增加操作系统调用时的传输大小来提高应用程序的性能。这个测试正在写入一个新文件,因此元数据的开销也包含在测量中。 | — |
Frewrite | 这个测试测试了使用库函数fwrite()写文件的性能。这是一个库例程,执行缓冲和阻塞的写操作。缓冲区在用户的缓冲区内地址空间。如果应用程序要写入非常小的传输,那么fwrite()的缓冲和阻塞I/O功能可以通过减少实际操作系统调用的数量和增加操作系统调用时的传输大小来提高应用程序的性能。这个测试是写入一个已存在的文件,因此性能应该更高,因为不需要元数据操作。 | — |
Fread | 这个测试使用库函数fread()读取文件的性能。这是一个库例程,执行缓冲和阻塞的读取操作。缓冲区在用户的地址空间内。如果应用程序需要读取非常小的传输,那么fread()的缓冲和阻塞I/O功能可以通过减少实际操作系统调用的数量和增加操作系统调用时的传输大小来提高应用程序的性能。 | — |
Freread | 这个测试与上面的fread相同,不同的是,在这个测试中,正在读取的文件是最近读取的。这应该会带来更高的性能,因为操作系统可能会将文件数据缓存在缓存中。 | — |
Mmap | 许多操作系统支持使用mmap()将文件映射到用户的地址空间中。一旦映射到位,然后存储到内存中的这个位置,将导致数据存储到文件中。如果应用程序希望将文件视为内存块,这很方便。例如,在内存中有一个数组,同时在文件系统中作为文件维护。mmap文件的语义与普通文件有些不同。如果存储到内存位置完成了,那么实际的文件I/O可能不会立即发生。使用带有MS_SYNC和MS_ASYNC标志的msyc()可以控制内存和文件的一致性。使用MS_SYNC调用msync()将强制将内存中的内容存储到文件中,并等待它在存储中,然后返回到应用程序。对msync()的调用带有MS_ASYNC标志,告诉操作系统使用异步机制将内存刷新到存储器,以便应用程序可以在不等待数据写入存储器的情况下返回执行。这个测试测试了使用mmap()机制执行I/O的性能。 | — |
Async I/O | 许多操作系统支持的另一种执行I/O的机制是POSIX异步I/O。应用程序使用POSIX标准异步I/O接口来完成这一工作。例如:aio_write()、aio_read()、aio_error()。这个测试测试了POSIX异步I/O机制的性能。 | — |
最简单的测试模式,记录大小从4k到16M,文件大小从64k到512M,测试包括:
write,rewrite,read,reread,random read,random write,bkwd read,record rewrite ,stride read ,fwrite,frewrite,fread freread
最后将结果以Excel的形式输出到文件。
$ iozone -a -Rb iozone.xls
Auto Mode
Using maximum file size of 10240 kilobytes.
Command line used: ./iozone -a -g 10M
Output is in kBytes/sec
Time Resolution = 0.000001 seconds.
Processor cache size set to 1024 kBytes.
Processor cache line size set to 32 bytes.
File stride size set to 17 * record size.
random random bkwd record stride
kB reclen write rewrite read reread read write read rewrite read fwrite frewrite fread freread
64 4 361867 586352 1002351 1087638 1002351 496362 639427 587635 1279447 532815 566551 557144 735831
64 8 424198 780776 1183548 1599680 1210227 592827 763021 725882 1562436 659861 688639 604849 916769
64 16 453587 799377 1452528 1780008 1452528 710511 831569 809014 1562436 718114 780776 592827 998622
$ iozone -a -n 1M -g 1G # 测试文件最小为1MB 最大为1GB
$ iozone -a -s 10M # 测试文件固定为10MB
$ iozone -a -y 1K -q 1M # 测试记录最小为1KB 最大为1MB
$ iozone -a -r 1K # 测试记录固定为 1KB
$ iozone -a -I # O_DIRECT
$ iozone -a -o # O_SYNC
$ ./iozone -i 0 -i 1
$ ./iozone -i 0 -i 2
当前是正常IO模式,因此有缓冲区高速缓存的存在,所以吞吐量很高
$ ./iozone -t 5 # 使用5个线程测试
Command line used: ./iozone -t 5
Output is in kBytes/sec
Time Resolution = 0.000001 seconds.
Processor cache size set to 1024 kBytes.
Processor cache line size set to 32 bytes.
File stride size set to 17 * record size.
Throughput test with 5 processes
Each process writes a 512 kByte file in 4 kByte records
Children see throughput for 5 initial writers = 812500.62 kB/sec
Parent sees throughput for 5 initial writers = 10746.34 kB/sec
Min throughput per process = 417651.66 kB/sec
Max throughput per process = 417651.66 kB/sec
Avg throughput per process = 162500.12 kB/sec
Min xfer = 512.00 kB
$ iozone -t 5 -T -I
O_DIRECT feature enabled
Command line used: ./iozone -t 5 -T -I
Output is in kBytes/sec
Time Resolution = 0.000001 seconds.
Processor cache size set to 1024 kBytes.
Processor cache line size set to 32 bytes.
File stride size set to 17 * record size.
Throughput test with 5 threads
Each thread writes a 512 kByte file in 4 kByte records
Children see throughput for 5 initial writers = 27016.68 kB/sec
Parent sees throughput for 5 initial writers = 20854.62 kB/sec
Min throughput per thread = 4480.45 kB/sec
Max throughput per thread = 6522.04 kB/sec
Avg throughput per thread = 5403.34 kB/sec
Min xfer = 392.00 kB