Linux下测量存储设备读/写性能的工具还是非常丰富的,例如我们下面要说的fio,还有dd,hdparm,ioping等等。本文我们主要说一下关于fio的使用。

关于fio

Fio 由 Jens Axboe 编写的一个开源I/O性能测试工具,它支持多种类型的I/O操作,包括顺序读写、随机读写等,可以模拟多种实际工作负载,用于评估存储设备的性能。

在管理 Linux 服务器时,尤其是在与数据库、虚拟化或任何 I/O 密集型任务相关的场景中,了解存储设备的性能至关重要。为此,fio是最可靠的工具之一 。此工具用途广泛,可以模拟各种 I/O 工作负载,以测试存储设备的性能。

“fio”可以在各种操作系统上使用,包括 Windows、macOS 和 FreeBSD等。但是,安装和使用可能因平台而异。

注意:

使用fio测试写性能时,如果直接向文件系统中写,会损坏电脑的分区,最终导致磁盘故障,所以记住:

1.不要使用fio向文件系统中测试读写,风险极高;

2.不要在生产服务器上测试任何不知道是否有风险的命令;

尽可能不要在系统分区做测试!!!!!!!!!!不要针对正在使用的设备运行具有写入的工作负载。

在使用fio进行测试过程中, filename参数指定某个要测试的裸设备(硬盘或分区),尽可能不在系统分区,这可能会破坏系统分区,而导致系统崩溃。

源代码

Fio 驻留在 git 存储库中,规范位置为:

https://git.kernel.dk/cgit/fio/

格式fio-git-*.tar.gz,包括 git 元数据也是如此。其他压缩包是官方 fio 版本的存档。 快照可从以下位置下载:

https://brick.kernel.dk/snaps/

还有两个官方mirrors。可以安全地用作备份:

https://git.kernel.org/pub/scm/linux/kernel/git/axboe/fio.git

https://github.com/axboe/fio.git

二进制包

Debian的:

从 Debian “Squeeze” 开始,fio 软件包是官方 Debian 仓库。https://packages.debian.org/search?keywords=fio .

Ubuntu的:

从 Ubuntu 10.04 LTS(又名“Lucid Lynx”)开始,fio 软件包是其中的一部分 Ubuntu “universe” 仓库。https://packages.ubuntu.com/search?keywords=fio .

Red Hat、Fedora、CentOS 等:

从 Fedora 9/Extra Packages for Enterprise Linux 4 开始,fio 软件包是 Fedora/EPEL 仓库的一部分。https://packages.fedoraproject.org/pkgs/fio/ .

windows:

Linux fio磁盘性能测试工具使用和示例_作业文件

从 fio 3.31 开始,标记版本的 Windows 安装程序是 可在 GitHub 上找到,网址为 https://github.com/axboe/fio/releases。这 Windows 的最新安装程序也可以作为 GitHub Actions 获取 通过从 https://github.com/axboe/fio/actions 中选择构建来创建工件。这些需要登录到 GitHub 帐户。

其他linux可以去官网查看。


安装“fio”

在运行任何测试之前,我们需要确保 fio 安装在我们的 Linux 机器上。

Ubuntu:

sudo apt-get update && sudo apt-get install fio -y

Oracle Linux 或 CentOS 

sudo dnf install fio -y
sudo yum install fio -y

仓库中没有自行编译

tar -xzvf fio-x.x.x.tar.gz  //下载压缩包并上传后,解压
cd fio-x.x.x  
//自行编译
./configure  
make  
sudo make install

请注意,在以下平台上 GNU make 不是默认的,GNU make 是必需的。在 BSD 上,它可以从 devel/gmake 获得 ports 目录;在 Solaris 上,它位于 SUNWgmake 软件包中。

Configure 将打印启用的选项。请注意,在基于 Linux 的平台上, 必须安装 libaio 开发包才能使用。根据发行版的不同,它通常被称为 libaio-devel 或 libaio-dev。

对于 gfio,需要 gtk 2.18(或更高版本)、关联的 glib 线程和 cairo 要安装。GFIO不是自动构建的,可以通过配置选项进行启用。

要使用交叉编译器构建 fio:

$ make clean
$ make CROSS_COMPILE=/path/to/toolchain/prefix

Configure 将尝试自动确定目标平台。

也可以为 ESX 构建 fio,请使用 switch to 配置。--esx

windows下安装

如何在 64 位 Windows 上源码编译 fio:

  1. 安装 Cygwin (https://www.cygwin.com/)。安装 make 和 所有 以 mingw64-x86_64 开头的软件包。如果您愿意,请确保安装了 mingw64-x86_64-zlib 启用 fio 的日志压缩功能。
  2. 打开 Cygwin 终端。
  3. 进入 fio 目录(源文件)。
  4. run。make clean && make -j

window下的直接安装,下载x64或32位已经编译好的安装文件。fio-x.xx-x64.msi或fio-x.xx-x86.msi。

下载后,双击安装。

Linux fio磁盘性能测试工具使用和示例_作业文件_02

安装完毕以后,在C:\Program Files\fio目录下找到fio.exe并双击,然后在当前目录下按住shift键,右键打开PowerShell,输入fio –version,出现版本信息,说明安装成功。


基本“fio”命令

要使用 fio 运行基本测试,请使用以下命令:

$  fio --name=test --ioengine=sync --rw=randwrite --bs=4k --numjobs=1 --size=1G --runtime=10m --time_based

以下是参数的细分:

  • –name=test:将作业命名为“test”。
  • –ioengine=sync:指定要使用的 I/O 引擎。
  • –rw=randwrite:这会将 I/O 模式设置为随机写入。
  • –bs=4k:这会将块大小设置为 4KB。
  • –numjobs=1:这将运行一个作业/线程。
  • –size=1G:这会将作业的 I/O 总大小设置为 1GB。
  • –runtime=10m:这会将作业限制为 10 分钟。
  • –time_based:这将使作业在指定时间内运行,而不考虑 I/O 的数量。

例如:

test: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=sync, iodepth=1
fio-3.27
Starting 1 process
Jobs: 1 (f=1): [w(1)][100.0%][w=4056KiB/s][w=1014 IOPS][eta 00m:00s]
test: (groupid=0, jobs=1): err= 0: pid=12345: Fri Oct 13 10:10:10 2023
  write: IOPS=1012, BW=4048KiB/s (4147kB/s)(600MiB/152022msec)
    clat (usec): min=2, max=1058, avg= 4.66, stdev= 2.31
     lat (usec): min=2, max=1058, avg= 4.68, stdev= 2.32
    clat percentiles (usec):
     |  1.00th=[    3],  5.00th=[    3], 10.00th=[    3], 20.00th=[    4],
     | 30.00th=[    4], 40.00th=[    4], 50.00th=[    4], 60.00th=[    4],
     | 70.00th=[    4], 80.00th=[    5], 90.00th=[    5], 95.00th=[    5],
     | 99.00th=[    6], 99.50th=[    7], 99.90th=[   11], 99.95th=[   13],
     | 99.99th=[   21]
  lat (usec)   : 4=60.01%, 10=39.96%, 20=0.02%, 50=0.01%
  cpu          : usr=1.23%, sys=4.56%, ctx=154011, majf=0, minf=8
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.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.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,153600,0,0 short=153600,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
  WRITE: bw=4048KiB/s (4147kB/s), 4048KiB/s-4048KiB/s (4147kB/s-4147kB/s), io=600MiB (629MB), run=152022-152022msec

Disk stats (read/write):
  sda: ios=0/153594, merge=0/789, ticks=0/615, in_queue=615, util=0.40%

要测量读取和写入性能,可以调整 –rw 参数:

  • 对于随机读取:–rw=randread
  • 对于随机写入:–rw=randwrite
  • 对于顺序读取:–rw=read
  • 对于顺序写入:–rw=write

结果解读

测试完成后,fio 将提供详细的输出。需要注意的最重要的指标是:

1. 测试配置:

test: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=sync, iodepth=1
  • rw=randwrite:测试设置为执行随机写入。
  • bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B:读取、写入和总操作的块大小设置为 4KB。
  • ioengine=sync:I/O 操作同步执行。
  • iodepth=1:I/O 操作队列的深度设置为 1,表示一次处理一个操作。

2. 绩效指标:

write: IOPS=1012, BW=4048KiB/s (4147kB/s)(600MiB/152022msec)
  • IOPS=1012:存储设备的 I/O 性能为每秒 1012 次输入/输出操作。
  • BW=4048KiB/s (4147kB/s):带宽或数据传输速率约为 4048 KiB/s(或 4147 kB/s)。
  • 600MiB/152022 毫秒:在 152,022 毫秒(或大约 152 秒)内总共写入了 600 MiB 的数据。

3. 延迟指标:

clat (usec): min=2, max=1058, avg= 4.66, stdev= 2.31
  • clat (usec):这是指完成延迟,即完成 I/O 操作所需的时间。
  • min=2,max=1058:最快的 I/O 操作需要 2 微秒,而最慢的 I/O 操作需要 1058 微秒。
  • avg= 4.66:平均而言,I/O 操作大约需要 4.66 微秒。
  • stdev= 2.31:衡量延迟可变性的标准差为 2.31 微秒。

4. 延迟百分位数:

百分位数提供对延迟值分布的见解。例如:

  • 1.00th=[3]:1% 的 I/O 操作的延迟为 3 微秒或更短。
  • 99.99th=[21]:99.99% 的 I/O 操作延迟为 21 微秒或更短。

5. CPU使用率:

cpu: usr=1.23%, sys=4.56%, ctx=154011, majf=0, minf=8
  • usr=1.23%:在测试期间,1.23% 的 CPU 用于用户级进程。
  • sys=4.56%:4.56% 的 CPU 用于系统级进程。
  • ctx=154011:测试期间发生的上下文切换次数。
  • majf=0, minf=8:主要和次要页面错误。当必须从磁盘检索数据时(不理想),就会发生重大故障,而次要故障会检索内存中其他位置的数据。

6. 磁盘统计:

sda: ios=0/153594, merge=0/789, ticks=0/615, in_queue=615, util=0.40%
  • ios=0/153594:在 sda 磁盘上没有读取操作 (ios=0),执行了 153,594 次写入操作。
  • merge=0/789:未发生读取合并,发生 789 次写入合并。合并是指在处理之前合并的操作。
  • ticks=0/615:读取和写入所花费的时间。在本例中,写入花费了 615 毫秒。
  • in_queue=615:操作排队的总时间。
  • util=0.40%:测试期间的磁盘利用率。

FIO 命令分解执行

IOPS 性能测试

测试随机读取

sudo fio --filename=device name --direct=1 --rw=randread --bs=4k --ioengine=libaio --iodepth=256 --runtime=120 --numjobs=4 --time_based --group_reporting --name=iops-test-job --eta-newline=1 --readonly

在某些情况下,如果使用作业文件而不是直接运行命令,可能会看到更一致的结果。对于此方法,请使用以下步骤。

使用以下内容创建作业文件 fiorandomread.fio:

[global]
bs=4K
iodepth=256
direct=1
ioengine=libaio
group_reporting
time_based
runtime=120
numjobs=4
name=raw-randread
rw=randread
							
[job1]
filename=device name

使用以下命令运行作业:

fio randomread.fio

测试文件随机读/写

对挂载点运行以下命令以测试文件读/写:

sudo fio --filename=/custom mount point/file --size=500GB --direct=1 --rw=randrw --bs=4k --ioengine=libaio --iodepth=256 --runtime=120 --numjobs=4 --time_based --group_reporting --name=iops-test-job --eta-newline=1

测试随机读/写

不要直接针对正在使用的设备运行具有写入工作负载 (readwriterandrwwritetrimwrite ) 的 FIO 测试

执行以下命令,测试随机读/写操作。

sudo fio --filename=device name --direct=1 --rw=randrw --bs=4k --ioengine=libaio --iodepth=256 --runtime=120 --numjobs=4 --time_based --group_reporting --name=iops-test-job --eta-newline=1

在某些情况下,如果使用作业文件而不是直接运行命令,可能会看到更一致的结果。对于此方法,请使用以下步骤。

使用以下内容创建作业文件 fiorandomreadwrite.fio:

[global]
bs=4K
iodepth=256
direct=1
ioengine=libaio
group_reporting
time_based
runtime=120
numjobs=4
name=raw-randreadwrite
rw=randrw
							
[job1]
filename=device name

使用以下命令运行作业:

fio randomreadwrite.fio

测试顺序读

对于使您能够利用顺序访问模式的工作负载(如数据库工作负载),可以通过测试顺序读取来确认此模式的性能。

sudo fio --filename=device name --direct=1 --rw=read --bs=4k --ioengine=libaio --iodepth=256 --runtime=120 --numjobs=4 --time_based --group_reporting --name=iops-test-job --eta-newline=1 --readonly

在某些情况下,如果使用作业文件而不是直接运行命令,可能会看到更一致的结果。对于此方法,请使用以下说明:

使用以下内容创建作业文件 fioread.fio:

[global]
bs=4K
iodepth=256
direct=1
ioengine=libaio
group_reporting
time_based
runtime=120
numjobs=4
name=raw-read
rw=read
							
[job1]
filename=device name

使用以下命令运行作业:

fio read.fio

吞吐量性能测试

使用以下 FIO 示例命令测试吞吐量性能。

测试随机读取

sudo fio --filename=device name --direct=1 --rw=randread --bs=256k --ioengine=libaio --iodepth=64 --runtime=120 --numjobs=4 --time_based --group_reporting --name=throughput-test-job --eta-newline=1 --readonly

测试文件随机读/写

sudo fio --filename=/custom mount point/file --size=500GB --direct=1 --rw=randrw --bs=64k --ioengine=libaio --iodepth=64 --runtime=120 --numjobs=4 --time_based --group_reporting --name=throughput-test-job --eta-newline=1 

测试随机读/写

不要直接针对正在使用的设备运行具有写入工作负载 (readwriterandrwwritetrimwrite ) 的 FIO 测试

sudo fio --filename=device name --direct=1 --rw=randrw --bs=256k --ioengine=libaio --iodepth=64 --runtime=120 --numjobs=4 --time_based --group_reporting --name=throughput-test-job --eta-newline=1

测试顺序读取

sudo fio --filename=device name --direct=1 --rw=read --bs=256k --ioengine=libaio --iodepth=64 --runtime=120 --numjobs=4 --time_based --group_reporting --name=throughput-test-job --eta-newline=1 --readonly

延迟性能测试

测试随机读取的延迟

sudo fio --filename=device name --direct=1 --rw=randread --bs=4k --ioengine=libaio --iodepth=1 --numjobs=1 --time_based --group_reporting --name=readlatency-test-job --runtime=120 --eta-newline=1 --readonly

在某些情况下,如果使用作业文件而不是直接运行命令,可能会看到更一致的结果。对于此方法,请使用以下步骤。

使用以下内容创建作业文件 fiorandomreadlatency.fio:

[global]
bs=4K
iodepth=1
direct=1
ioengine=libaio
group_reporting
time_based
runtime=120
numjobs=1
name=readlatency-test-job
rw=randread
							
[job1]
filename=device name

使用以下命令运行作业:

fio fiorandomreadlatency.fio

测试随机读/写延迟

不要直接针对正在使用的设备运行具有写入工作负载 (readwriterandrwwritetrimwrite ) 的 FIO 测试

sudo fio --filename=device name --direct=1 --rw=randrw --bs=4k --ioengine=libaio --iodepth=1 --numjobs=1 --time_based --group_reporting --name=rwlatency-test-job --runtime=120 --eta-newline=1

在某些情况下,如果使用作业文件而不是直接运行命令,可能会看到更一致的结果。对于此方法,请使用以下步骤。

使用以下内容创建作业文件 fiorandomrwlatency.fio:

[global]
bs=4K
iodepth=1
direct=1
ioengine=libaio
group_reporting
time_based
runtime=120
numjobs=1
name=rwlatency-test-job
rw=randrw
							
[job1]
filename=device name

使用以下命令运行作业:

fio fioradomrwlatency.fio

错误的命令会损坏系统

错误的使用fio测试随机读的命令:

# 错误原因主要是-filename=/dev/mapper/centos-root,不应当适用-filename制定磁盘的文件系统名称,而是应当在要测试的磁盘中创建一个目录,指定为该目录下的一个文件
fio -name=test -filename=/dev/mapper/centos-root -direct=1 -iodepth=20 -thread -rw=randread -ioengine=libaio -bs=16k -size=1G -numjobs=2 -runtime=300 -group_reporting

错误的使用fio测试随机写的命令:

# 错误原因是不应当使用 -filename=/dev/mapper/centos-root指定文件系统的名称,这样会损坏文件系统的分区
fio -name=test -filename=/dev/mapper/centos-root -direct=1 -iodepth=20 -thread -rw=randwrite -ioengine=libaio -bs=16k -size=1G -numjobs=2 -runtime=300 -group_reporting -allow_mounted_write=1

正确的使用fio测试随机读的命令:

# 这样会操作/home目录下的test文件,不会影响文件系统
fio -name=test -filename=/home/test -direct=1 -iodepth=20 -thread -rw=randread -ioengine=libaio -bs=16k -size=1G -numjobs=2 -runtime=300 -group_reporting

正确的使用fio测试随机写的命令:

# 这样会随机写/home下面的test文件,不会对文件系统产生任何影响,也不会导致磁盘故障和格式化重装
fio -name=test -filename=/home/test -direct=1 -iodepth=20 -thread -rw=randwrite -ioengine=libaio -bs=16k -size=1G -numjobs=2 -runtime=300 -group_reporting -allow_mounted_write=1