FreeBSD で ZFS を利用する – ファイルシステムの圧縮を利用する・比較する

ZFS

今回は ZFS の大きな特徴の一つである,圧縮にフォーカスしたいと思います.
ZFS はファイルシステム (ZVOLも) の圧縮が利用でき,透過的に圧縮・展開が行われます.
これによってストレージ利用量の削減が見込めます.

ファイルシステムの圧縮

ZFS でのファイルシステムの圧縮にはいくつかのアルゴリズムがあります.
それぞれ得手・不得手がありますので格納するデータに応じた圧縮方式を適用することが推奨されます.

  • LZ4
    圧縮・展開の速さ,CPU 負荷の少なさに定評があり,現在 compression=on の場合のデフォルト値となっている.ZSTD よりも高速と言われている.
  • GZIP
    圧縮率は高いが CPU 負荷も高い.バックアップ領域など静的なデータを長期保存し普段読み書きアクセスを頻繁に行わない所には良いと思う.
  • LZJB
    LZ4 と GZIP の中間位の立ち位置で,圧縮率に優れている.展開は LZ4 の方が速い.
  • ZLE
    連続するゼロデータ (0 が連続するデータ) の所のみ圧縮を行う.負荷は低いが効果も低い.
  • ZSTD
    たぶん今後のスタンダードになるもの.圧縮・展開の速さは LZ4 と同等,圧縮率が GZIP に近しい.CPU 負荷は LZ4 より少し高い.というもの

と,色々ありますので,それぞれどのような効果・パフォーマンスなのかを測定してみます.

それぞれのアルゴリズムでの圧縮・展開の測定

測定の方法ですが,各ファイルシステムにFreeBSD のソースファイル「src_stable_13.tar.xz」を展開して展開にかかる時間,圧縮率の測定.
また,逆に展開されたソースファイル群を tar で読み出して /dev/null に書き出してかかる時間を測定してみます.

時間に関しては仮想環境上ですのでブレが生じる事を前提に見て頂ければと思います.
CPU 負荷についてはこれも仮想上なのでより参考にできないと思いますので取得しません.

LZ4

まず,LZ4 で圧縮するファイルシステムの作成を行います.

# zfs create pool0/lz4

# zfs set compression=lz4 pool0/lz4
# zfs get compression pool0/lz4
NAME       PROPERTY     VALUE           SOURCE
pool0/lz4  compression  lz4             local

# mkdir /pool0/lz4/src1
# mkdir /pool0/lz4/src2
# mkdir /pool0/lz4/src3

3回実施して計測しますので,/pool0/lz4/src[1-3] ができると理解ください.

書き込み: 1回目

# cd /pool0/lz4/src1

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 13:25:38 JST 2023
Sat Dec 23 13:26:01 JST 2023

# zfs get compressratio pool0/lz4
NAME       PROPERTY       VALUE  SOURCE
pool0/lz4  compressratio  2.42x  -

書き込み: 2回目

# cd /pool0/lz4/src2

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 13:27:29 JST 2023
Sat Dec 23 13:27:50 JST 2023

# zfs get compressratio pool0/lz4
NAME       PROPERTY       VALUE  SOURCE
pool0/lz4  compressratio  2.42x  -

書き込み: 3回目

# cd /pool0/lz4/src3

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 13:28:55 JST 2023
Sat Dec 23 13:29:17 JST 2023

# zfs get compressratio pool0/lz4
NAME       PROPERTY       VALUE  SOURCE
pool0/lz4  compressratio  2.42x  -

書き込み: まとめ

1回目 23秒,2回目 21秒,3回目 22秒.平均22秒かかりました.
圧縮率は 2.42 ということで元データと比較して 140% の圧縮率でした.
なお,1.00 が無圧縮となります

ちなみに,展開したデータの実容量としては次のとおり 613MB です.

# du -sk /pool0/lz4/src1
628350  /pool0/lz4/src1

読み出し: 1回目

# cd /pool0/lz4/src1

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 13:34:21 JST 2023
Sat Dec 23 13:34:26 JST 2023

読み出し: 2回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 13:35:09 JST 2023
Sat Dec 23 13:35:13 JST 2023

読み出し: 3回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 13:35:58 JST 2023
Sat Dec 23 13:36:01 JST 2023

読み出し: まとめ

1回目が5秒,2回目が4秒,3回目が3秒でした.ですので平均4秒で 630MB の読み出しができている事になります.
なお,2回目以降はキャッシュに入ったので速度が上がる可能性が高いです.

GZIP

まず,GZIP で圧縮するファイルシステムの作成を行います.

# zfs create pool0/gzip

# zfs set compression=gzip pool0/gzip

# zfs get compression pool0/gzip
NAME        PROPERTY     VALUE           SOURCE
pool0/gzip  compression  gzip            local

# mkdir /pool0/gzip/src1
# mkdir /pool0/gzip/src2
# mkdir /pool0/gzip/src3

3回実施して計測しますので,/pool0/gzip/src[1-3] ができると理解ください.

書き込み: 1回目

# cd /pool0/gzip/src1

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 13:41:44 JST 2023
Sat Dec 23 13:42:23 JST 2023

# zfs get compressratio pool0/gzip
NAME        PROPERTY       VALUE  SOURCE
pool0/gzip  compressratio  3.60x  -

書き込み: 2回目

# cd /pool0/gzip/src2

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 13:43:17 JST 2023
Sat Dec 23 13:43:57 JST 2023

# zfs get compressratio pool0/gzip
NAME        PROPERTY       VALUE  SOURCE
pool0/gzip  compressratio  3.59x  -

書き込み: 3回目

# cd /pool0/gzip/src3
# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 13:44:46 JST 2023
Sat Dec 23 13:45:25 JST 2023

# zfs get compressratio pool0/gzip
NAME        PROPERTY       VALUE  SOURCE
pool0/gzip  compressratio  3.59x  -

書き込み: まとめ

1回目 39秒,2回目 40秒,3回目 39秒.平均39秒かかりました.
圧縮率は 3.59 ということで元データと比較して 260% の圧縮率でした.
LZ4 と比べて時間 (CPU 負荷) は高いものの,圧縮率はとても良いことが分かります.

読み出し: 1回目

# cd /pool0/gzip/src1

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 13:49:34 JST 2023
Sat Dec 23 13:49:56 JST 2023

読み出し: 2回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 13:50:01 JST 2023
Sat Dec 23 13:50:09 JST 2023

読み出し: 3回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 13:50:49 JST 2023
Sat Dec 23 13:50:57 JST 2023

読み出し: まとめ

1回目が22秒,2回目が8秒,3回目が8秒でした.ですので平均13秒で 630MB の読み出しができている事になります.
なお,2回目以降はキャッシュに入ったので速度が上がる可能性が高いです.
LZ4 と1回目の比較をすると17秒の違いがありますので,圧縮データの展開時も CPU 負荷は高めだと思います.

LZJB

まず,LZJB で圧縮するファイルシステムの作成を行います.

# zfs create pool0/lzjb

# zfs set compression=lzjb pool0/lzjb

# zfs get compression pool0/lzjb
NAME        PROPERTY     VALUE           SOURCE
pool0/lzjb  compression  lzjb            local


# mkdir /pool0/lzjb/src1
# mkdir /pool0/lzjb/src2
# mkdir /pool0/lzjb/src3

3回実施して計測しますので,/pool0/lzjb/src[1-3] ができると理解ください.

書き込み: 1回目

# cd /pool0/gzip/src1

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 13:58:24 JST 2023
Sat Dec 23 13:58:51 JST 2023

# zfs get compressratio pool0/lzjb
NAME        PROPERTY       VALUE  SOURCE
pool0/lzjb  compressratio  2.12x  -

書き込み: 2回目

# cd /pool0/lzjb/src2

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 13:59:36 JST 2023
Sat Dec 23 13:59:58 JST 2023

# zfs get compressratio pool0/lzjb
NAME        PROPERTY       VALUE  SOURCE
pool0/lzjb  compressratio  2.12x  -

書き込み: 3回目

# cd /pool0/lzjb/src3

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 14:00:43 JST 2023
Sat Dec 23 14:01:05 JST 2023

# zfs get compressratio pool0/lzjb
NAME        PROPERTY       VALUE  SOURCE
pool0/lzjb  compressratio  2.12x  -

書き込み: まとめ

1回目 27秒,2回目 22秒,3回目 22秒.平均24秒かかりました.
圧縮率は 2.12 ということで元データと比較して 210% の圧縮率でした.
LZ4 と比べて時間 (CPU 負荷) は高いものの,GZIP 程ではなく,圧縮率も GZIP 程ではないものの良い結果となっています.

読み出し: 1回目

# cd /pool0/lzjb/src1

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:05:17 JST 2023
Sat Dec 23 14:05:59 JST 2023

読み出し: 2回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:06:34 JST 2023
Sat Dec 23 14:06:40 JST 2023

読み出し: 3回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:07:05 JST 2023
Sat Dec 23 14:07:12 JST 2023

読み出し: まとめ

1回目が42秒,2回目が6秒,3回目が7秒でした.初回が GZIP より時間がかかっているのは予定外です.本来は少なくなるはず… 平均18秒で 630MB の読み出しができている事になります.
2回目,3回目の値が GZIP に比べて低いため,やり直せば1回目も値が違ってきているとは思います.
いずれにぜよ,速度・圧縮率の観点で LZ4 と GZIP の間に位置する事はわかるかと思います.

ZLE

まず,ZLE で圧縮するファイルシステムの作成を行います.

# zfs create pool0/zle

# zfs set compression=zle pool0/zle

# zfs get compression pool0/zle
NAME       PROPERTY     VALUE           SOURCE
pool0/zle  compression  zle             local

# mkdir /pool0/zle/src1
# mkdir /pool0/zle/src2
# mkdir /pool0/zle/src3

3回実施して計測しますので,/pool0/zle/src[1-3] ができると理解ください.

書き込み: 1回目

# cd /pool0/zle/src1

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 14:22:48 JST 2023
Sat Dec 23 14:23:13 JST 2023

# zfs get compressratio pool0/zle
NAME       PROPERTY       VALUE  SOURCE
pool0/zle  compressratio  1.07x  -

書き込み: 2回目

# cd /pool0/zle/src2

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 14:24:41 JST 2023
Sat Dec 23 14:25:06 JST 2023

# zfs get compressratio pool0/zle
NAME       PROPERTY       VALUE  SOURCE
pool0/zle  compressratio  1.07x  -

書き込み: 3回目

# cd /pool0/zle/src3

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 14:25:46 JST 2023
Sat Dec 23 14:26:10 JST 2023

# zfs get compressratio pool0/zle
NAME       PROPERTY       VALUE  SOURCE
pool0/zle  compressratio  1.07x  -

書き込み: まとめ

1回目 25秒,2回目 25秒,3回目 24秒.平均25秒かかりました.
圧縮率は 1.07 ということで元データと比較して 10% 未満の圧縮率でした.
初めて試してみましたが,これは自分が採用する事はないな.と思いました.
通常のファイルサーバーとしての利用の場合,これを採用するメリットはないと思います.データベース製品で最初にファイルシステムにゼロ埋めを行うものがありますが,こういったものには有効なのだと思いますが…

読み出し: 1回目

# cd /pool0/zle/src1

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:30:22 JST 2023
Sat Dec 23 14:31:08 JST 2023

読み出し: 2回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:31:35 JST 2023
Sat Dec 23 14:32:05 JST 2023

読み出し: 3回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:32:30 JST 2023
Sat Dec 23 14:32:53 JST 2023

読み出し: まとめ

1回目が46秒,2回目が30秒,3回目が23秒でした.圧縮されているデータがそもそも少ないため,読み出しにかかる量が多くなりその結果時間がかかっているという状況だと思います.

ZSTD

まず,ZSTD で圧縮するファイルシステムの作成を行います.

# zfs create pool0/zstd
root@bsd13-1:/pool0/zle/src1 # zfs set compression=zstd pool0/zstd
root@bsd13-1:/pool0/zle/src1 # zfs get compression pool0/zstd
NAME        PROPERTY     VALUE           SOURCE
pool0/zstd  compression  zstd            local

# mkdir /pool0/zstd/src1
# mkdir /pool0/zstd/src2
# mkdir /pool0/zstd/src3

3回実施して計測しますので,/pool0/zstd/src[1-3] ができると理解ください.

書き込み: 1回目

# cd /pool0/zstd/src1

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 14:38:29 JST 2023
Sat Dec 23 14:38:52 JST 2023

# zfs get compressratio pool0/zstd
NAME        PROPERTY       VALUE  SOURCE
pool0/zstd  compressratio  3.47x  -

書き込み: 2回目

# cd /pool0/zstd/src2

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 14:39:45 JST 2023
Sat Dec 23 14:40:07 JST 2023

# zfs get compressratio pool0/zstd
NAME        PROPERTY       VALUE  SOURCE
pool0/zstd  compressratio  3.47x  -

書き込み: 3回目

# cd /pool0/zstd/src3

# date ; tar -Jxf /root/src_stable_13.tar.xz ; date
Sat Dec 23 14:40:58 JST 2023
Sat Dec 23 14:41:21 JST 2023

# zfs get compressratio pool0/zstd
NAME        PROPERTY       VALUE  SOURCE
pool0/zstd  compressratio  3.47x  -

書き込み: まとめ

1回目 23秒,2回目 22秒,3回目 23秒.平均23秒かかりました.
圧縮率は 3.47 ということで元データと比較して 240% の圧縮率でした.
GZIP よりは多少劣りますがかかる時間は LZ4 並みの時間でした.

読み出し: 1回目

# cd /pool0/zstd/src1

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:45:21 JST 2023
Sat Dec 23 14:45:36 JST 2023

読み出し: 2回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:46:13 JST 2023
Sat Dec 23 14:46:26 JST 2023

読み出し: 3回目

# date ; tar -cf /dev/null ./ ; date
Sat Dec 23 14:46:47 JST 2023
Sat Dec 23 14:47:15 JST 2023

読み出し: まとめ

1回目が15秒,2回目が13秒,3回目が28秒でした.3回目が遅いのは環境の問題が高いと思います.
平均としては19秒で,GZIP よりは速く,LZ4 や LZJB より遅いという結果です.

まとめ

これらを纏めると次のとおりとなります.

書き込み時 (圧縮時)

アルゴリズム1回目2回目3回目平均圧縮率
LZ423秒21秒22秒22秒2.42
GZIP39秒40秒39秒39秒3.59
LZJB27秒22秒22秒24秒2.12
ZLE25秒25秒25秒24秒1.07
ZSTD23秒22秒23秒23秒3.47

書き込み時の速度で並べると LZ4 -> ZSTD -> LZJB | ZLE -> GZIP の順番
圧縮率で並べると GZIP -> ZSTD -> LZ4 -> LZJB -> ZLE の順番でした.

読み出し時 (展開時)

アルゴリズム1回目2回目3回目平均
LZ45秒4秒3秒4秒
GZIP22秒8秒8秒13秒
LZJB42秒6秒7秒18秒
ZLE46秒30秒23秒33秒
ZSTD15秒13秒28秒19秒

読み出し時の速度で見ると LZ4 -> GZIP -> ZSTD -> LZJB -> ZLE の順番でした.

仮想環境上での比較ですのでちょっとしたことでブレが発生しますが,それぞれの圧縮アルゴリズムの特徴が理解できたのではないでしょうか.

ファイルサーバーとして読み書き速度を最重要視したい場合は LZ4 になると思います.圧縮率も重視したい場合は ZSTD を選択.という形に.また,アーカイブやバックアップ目的は GZIP を採用というのが特性に合っているかと思います.

実際の所は自身のファイルサーバーの目的・役割に応じて選択いただくことになりますが,概ねの傾向として参考にして頂ければと思います.

コメント

タイトルとURLをコピーしました