為什麼 fio seq_writes 比 dd 快這麼多?
我有一個 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 的吞吐量生成一個包含隨機數據的 16GiB 文件。117 兆字節/秒。
現在,我嘗試使用fio,
# 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 創建文件,然後 issueopen
和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
我將重新建構您的問題以突出一些上下文:
為什麼是
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 的 FreeBSD 11.2 系統上配置為啟用壓縮的 RAIDZ2?
一個主要的區別是 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): min=28, max=2585, avg=48.03, stdev=24.04
你的旋轉磁碟真的能在 28 微秒內完成一次 I/O 嗎?如果不是,它可能會在某處緩衝)
最後,fio 預設在後續 blocks 中重用相同的模式。由於正在進行壓縮,這可以進一步提高您的
fio
吞吐量(但這將取決於 ZFS 記錄大小等因素)。要檢查這一點,請告訴 fio 使其緩衝區不可壓縮(這反過來會打開refill_buffers
)並查看吞吐量是否下降(在您的情況下它會下降)。TLDR;你給出的
fio
anddd
命令沒有測試同樣的東西。您需要注意諸如您的文件是否已經以正確的大小存在、您正在寫入的數據的可壓縮性以及您是否通過寫入太少的數據而不檢查它是否全部被寫回來考慮諸如核心緩沖之類的事情到磁碟。