ZFS圧縮のLZ4とZStandardを簡易比較(zstdがよさげ)

ZFSerの皆様におかれましては、OpenZFS 2.0で圧縮アルゴリズムにZStandardが追加されたのは周知の事実だろう。compressionの値としてzstd-Nzstd-fast-Nが指定できるようになったが、設定値と圧縮率の関係性は以下のとおり。

(速度重視)←   設定値   →(圧縮重視)
zstd-fast-1000 ~ zstd-fast-1 / zstd-1 ~ zstd-19

zstdzstd-fastで数値の関係性が逆転しているように見えるが(というか設定値上はそういう風にしか見えないのだが)、zstd-fastの方は負数を表しており、-1000が最小でスーパー速度重視ということなので一貫性が取れている。

ZStandardはLZ4より圧縮率が高く、それに応じて処理負荷も若干高いとされている。実際のところどんなものか、簡易的にテストした。

個人的にアーカイブ用途に使いたいので、圧縮率重視ってことでzstdのみが対象。だいぶてきとーな実験なので、あくまで傾向を掴むもの程度で見て欲しい。

ZFSの主要開発者の1人、Allan Judeによる真っ当なベンチマークも参照されたし。

テスト環境は以下のとおり。

  • テストデータ
    • 12675ファイル、503GiB(平均ファイルサイズ:40.6MiB)
    • OS・アプリのISOイメージ、zip、インストーラexe、Macのdmg、appバンドルなど圧縮が効きにくいデータが多数
  • テストマシン
    • OS: FreeBSD 13.0-RELEASE-p6 on Proxmox VE 7.1
    • CPU: 4 vCPU (Xeon E5-2680v4. オーバーコミットなし)
    • RAM: 64GB
    • HDD:
      • コピー元: RAID-Z2 (16TB 7200RPM SATA HDD×5)
      • コピー先: 単体 (10TB 7200RPM SATA HDD×1)

テストデータをコピー元のRAID-Z2プールから、テスト用のコピー先プールにrsyncでコピーする。cpじゃなくてrsyncなのは、終了時に転送速度を表示してくれて便利だからってだけで、他意はない。

圧縮アルゴリズム別のファイルシステムを作ってはコピーしての繰り返しで、途中プールの作り直しやファイルシステム削除はしてないので、HDDの外周/内周の転送速度差がテストに影響していることに注意。

加えて、仮想マシン上での実行だったり、テスト中もファイルサーバとして普通にアクセスしたり(といっても負荷をかけないよう自粛はしたけど)と、結果には様々なノイズが混入している点にも注意。

各圧縮方法ごとの圧縮後容量、圧縮率(無圧縮時を100%とした時の割合)、転送速度を下表にまとめる。

パターン 圧縮方法 容量(GiB) 圧縮率(%) 速度(MiB/s) 備考
1 lz4 483.6 96.3 115.8
2 zstd-3 477.3 95.0 115.0 数値なしのzstdを指定した場合に使われる値
3 zstd-7 476.5 94.8 111.0
ここで2~3を削除
4 zstd-15 476.3 94.8 100.4
5 zstd-19 475.3 94.6 24.5
6 gzip-9 478.8 95.3 71.6
7 zstd-3 477.3 95.0 112.0 HDDの外周/内周の影響確認用
8 lz4 483.6 96.3 109.4
9 off 502.4 100.0 108.9 無圧縮。基準値

パターン1~3実行後、一応、HDDの内外周差を気にしてパターン1,2のデータは削除している。

パターン9が基準値。無圧縮で最内周に書き込んでいるので、これより遅いかどうかで、圧縮処理がボトルネックになっているかの目安になるかなと。書き込み先がHDD 1台のプールなので、そこで律速されてる感があるけど、まぁ実際の使われ方に近い環境ってことで大目に見てください。

グラフで表したのが下図。

まず言えることはzstd-3のバランスの良さ。LZ4と遜色ない速度にもかかわらず、圧縮率は有意に高い。さすが、compress=zstdとした時に使われるレベルだけある。gzip-9より縮むのに大分速いってのは特筆すべき。

圧縮率最重視のzstd-19が当然ながら最も縮むが、速度が大分厳しい感じ。少なくとも今回のテストデータでは、処理時間に見合うだけの効果が得られているとは言い難い。仮に最新CPUで速度が10倍になったとしても、250MB/s程度でボトルネックとなる可能性が高く使いどころが難しそう。費用対効果が高いのはzstd-7、状況によってはzstd-15もなくはないかな。

ついでに、圧縮はrecordsizeが大きいほど効果的とされているので、その影響も軽く測定。

LZ4とZStandardのそれぞれで、レコードサイズを512kから1Mに変更した時の圧縮後容量の差分を求めたのが下表。

圧縮方法 recsize 圧縮後容量(MiB) 128kとの差分(MiB) 無圧縮容量に占める削減割合
lz4 128k 495251.3 - -
512k 495145.0 -106.3 -0.02%
1M 495251.4 +0.1 +0.00%
zstd-7 128k 490354.9 - -
512k 488842.4 -1512.5 -0.29%
1M 487907.2 -2447.7 -0.48%

なぜかLZ4のレコードサイズ1MBの時は圧縮率が下がってるけど、概ねレコードサイズが大きくなるほど圧縮率も向上するようだ。割合で見ると微々たるものだが、レコードサイズを変えるだけで恩恵が得られるのはありがたい。実のところ、レコードサイズを大きくすると実データに占めるメタデータ割合(ハッシュの量)が減り、プール容量的にはこちらの影響の方が大きかったりする(参考:ZFSのSpecial vdevを試してみる

とりあえず、互換性を気にしなくていい環境では、lz4の代わりに積極的にzstdを使っていくのが良さそう。可能な限りrecordsizeも大きくしていこう(ただし、FreeBSDはレコードサイズが128k超のファイルシステムからブート出来ない点には注意が必要。)




  • blog/2022/2022-02-21.txt
  • 最終更新: 2022-03-04 10:51
  • by Decomo