====== ZFS圧縮のLZ4とZStandardを簡易比較(zstdがよさげ) ====== ZFSerの皆様におかれましては、OpenZFS 2.0で圧縮アルゴリズムにZStandardが追加されたのは周知の事実だろう。compressionの値として''zstd-N''と''zstd-fast-N''が指定できるようになったが、設定値と圧縮率の関係性は以下のとおり。 |(速度重視)←   | 設定値 |   →(圧縮重視)| | zstd-fast-1000 ~ zstd-fast-1 / zstd-1 ~ zstd-19 ||| ''zstd''と''zstd-fast''で数値の関係性が逆転しているように見えるが(というか設定値上はそういう風にしか見えないのだが)、''zstd-fast''の方は負数を表しており、-1000が最小でスーパー速度重視ということなので一貫性が取れている。 ZStandardはLZ4より圧縮率が高く、それに応じて処理負荷も若干高いとされている。実際のところどんなものか、簡易的にテストした。 個人的にアーカイブ用途に使いたいので、圧縮率重視ってことで''zstd''のみが対象。だいぶてきとーな実験なので、あくまで傾向を掴むもの程度で見て欲しい。 ZFSの主要開発者の1人、Allan Judeによる[[https://docs.google.com/spreadsheets/d/1TvCAIDzFsjuLuea7124q-1UtMd0C9amTgnXm2yPtiUQ|真っ当なベンチマーク]]も参照されたし。 ===== テスト環境 ===== テスト環境は以下のとおり。 * テストデータ * 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台のプールなので、そこで律速されてる感があるけど、まぁ実際の使われ方に近い環境ってことで大目に見てください。 グラフで表したのが下図。 {{ :blog:2022:zfs_compression_comparison_lz4_vs_zstd.png |}} まず言えることは''zstd-3''のバランスの良さ。LZ4と遜色ない速度にもかかわらず、圧縮率は有意に高い。さすが、''compress=zstd''とした時に使われるレベルだけある。''gzip-9''より縮むのに大分速いってのは特筆すべき。 圧縮率最重視の''zstd-19''が当然ながら最も縮むが、速度が大分厳しい感じ。少なくとも今回のテストデータでは、処理時間に見合うだけの効果が得られているとは言い難い。仮に最新CPUで速度が10倍になったとしても、250MB/s程度でボトルネックとなる可能性が高く使いどころが難しそう。費用対効果が高いのは''zstd-7''、状況によっては''zstd-15''もなくはないかな。 ===== recordsizeによる圧縮率の変化 ===== ついでに、圧縮は''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の時は圧縮率が下がってるけど、概ねレコードサイズが大きくなるほど圧縮率も向上するようだ。割合で見ると微々たるものだが、レコードサイズを変えるだけで恩恵が得られるのはありがたい。実のところ、レコードサイズを大きくすると実データに占めるメタデータ割合(ハッシュの量)が減り、プール容量的にはこちらの影響の方が大きかったりする(参考:[[blog:2022:2022-02-24]]) とりあえず、互換性を気にしなくていい環境では、lz4の代わりに積極的にzstdを使っていくのが良さそう。可能な限りrecordsizeも大きくしていこう(ただし、FreeBSDはレコードサイズが128k超のファイルシステムからブート出来ない点には注意が必要。)