我有一个 zfs 服务器,我在其中运行了一些愚蠢的测试只是为了理解,这让我感到困惑。
上下文:- FreeBSD 11.2、启用压缩的 ZFS、SAS HDD、RAIDz2、768GB 内存。
这两个命令都直接在 FreeBSD 服务器上运行。
# time dd if=/dev/random of=./test_file bs=128k count=131072
131072+0 records in
131072+0 records out
17179869184 bytes transferred in 135.191596 secs (127077937 bytes/sec)
0.047u 134.700s 2:15.19 99.6% 30+172k 4+131072io 0pf+0w
# #The result file size:
# du -sh test_file
16G test_file
这表明我能够在 135 秒内处理包含随机数据的 16GiB 文件,吞吐量约为。 117 MiB/秒。
现在,我尝试使用菲奥,
# fio --name=seqwrite --rw=write --bs=128k --numjobs=1 --size=16G --runtime=120 --iodepth=1 --group_reporting
seqwrite: (g=0): rw=write, bs=(R) 128KiB-128KiB, (W) 128KiB-128KiB, (T) 128KiB-128KiB, ioengine=psync, iodepth=1
fio-3.6
Starting 1 process
seqwrite: Laying out IO file (1 file / 16384MiB)
Jobs: 1 (f=1): [W(1)][100.0%][r=0KiB/s,w=2482MiB/s][r=0,w=19.9k IOPS][eta 00m:00s]
seqwrite: (groupid=0, jobs=1): err= 0: pid=58575: Wed Jul 25 09:38:06 2018
write: IOPS=19.8k, BW=2478MiB/s (2598MB/s)(16.0GiB/6612msec)
clat (usec): min=28, max=2585, avg=48.03, stdev=24.04
lat (usec): min=29, max=2586, avg=49.75, stdev=25.19
bw ( MiB/s): min= 2295, max= 2708, per=99.45%, avg=2464.33, stdev=124.56, samples=13
iops : min=18367, max=21664, avg=19714.08, stdev=996.47, samples=13
---------- Trimmed for brevity -------------
Run status group 0 (all jobs):
WRITE: bw=2478MiB/s (2598MB/s), 2478MiB/s-2478MiB/s (2598MB/s-2598MB/s), io=16.0GiB (17.2GB), run=6612-6612msec
现在,我的吞吐量达到了 2478 MiB/s。同时使用带有随机数据的相同 16 GiB 文件。
为什么会有这么大的差别呢?我的理解是 dd 命令必须使用create
call 创建文件,然后发出open
,并write
调用将随机数据写入打开的文件中。最后是close
文件。我选择 128 K 的块大小来匹配 ZFS 默认记录大小。
fio 测试应该只测量调用write
,但其他一切都相同。为什么吞吐量差异如此之大?
更让我困惑的是,如果我要求 fio 创建一个具有 50% 压缩率的文件,吞吐量会下降到 847 MiB/s。我知道压缩涉及 CPU 工作,导致吞吐量下降,但我希望通过写入近一半的数据量来抵消其影响。知道为什么影响如此之大吗?
用于以 50% 压缩率运行 fio 的命令:
fio --name=seqwrite --rw=write --bs=128k --numjobs=1 --size=16G --runtime=60 --iodepth=1 --buffer_compress_percentage=50 --buffer_pattern=0xdeadbeef --group_reporting
答案1
我将重新组织你的问题以突出一些背景:
为什么是
fio --name=seqwrite --rw=write --bs=128k --numjobs=1 --size=16G --runtime=120 --iodepth=1 --group_reporting
比...快
time dd if=/dev/random of=./test_file bs=128k count=131072
在具有 768GB RAM、SAS HDD 和 ZFS 配置为启用压缩的 RAIDZ2 的 FreeBSD 11.2 系统上?
主要区别在于 fio 在对其进行计时测试之前预先创建文件:
seqwrite: Laying out IO file (1 file / 16384MiB)
而dd
可能会进行文件扩展写入(这将导致元数据更新)。此外,您有如此多的 RAM (768G),但与它 (16G) 相比,您写入的数据却很少,因此您的写入很有可能保存在 RAM 中(直到很久以后才真正写入磁盘)。这可能发生在fio
文件已预先制作并且每个 I/O 需要修改的文件元数据很少的情况下。您至少可以告诉 fio 不要说它已完成,直到作业结束时所有写入的数据都从内核写回end_fsync=1
。
(注意:当您看到完成延迟远低于您知道磁盘可以执行的延迟时,有一个微妙的提示表明 I/O 正在缓冲:
clat(usec):最小值=28,最大值=2585,平均值=48.03,stdev=24.04
你的旋转磁盘真的能在 28 微秒内完成一次 I/O 操作吗?如果不是,它可能会在某个地方被缓冲)
最后,fio 默认在后续块中重用相同的模式。由于正在进行压缩,这可以进一步提高fio
吞吐量(但这将取决于 ZFS 记录大小等因素)。要检查这一点,请告诉 fio 使其缓冲区不可压缩(这反过来会打开refill_buffers
)并查看吞吐量是否下降(在您的情况下确实如此)。
太长了;您给出的fio
和dd
命令不是在测试同一件事。您需要注意诸如文件是否已经以正确的大小存在,您正在写入的数据的可压缩性如何,以及您是否通过写入太少的数据而不检查是否已全部写回来考虑内核缓冲之类的事情到磁盘。