Zerofillデータの圧縮メソッドのベストチョイスは何か
Live With Linux::practical
- TOP
- Articles
- Live With Linux
- Zerofillデータの圧縮メソッドのベストチョイスは何か
序
unix-likeシステムにはgzipをはじめ様々な圧縮メソッドが存在する。
一般的なそれぞれの特徴、例えばgzipはオーソドックス、lz4は高速、bzip2やxzは低速でメモリ消費が大きいなどは知られた話だが、これがzerofillデータになるとどうだろうか?
zerofillデータは、それが前提になっているのであれば、サイズだけ記録されていれば復元可能なデータだ。 あまりにも単純で、極めて圧縮が効きやすいが、それ故に圧縮メソッド側で力を入れて想定するようなものでもない。 このことから、一般的な特徴とは大きく異なる結果が出る可能性がある。
zerofillデータの圧縮が特に重要になるのは、購入したばかりのPCのリカバリーイメージを作成するときだ。 汚れていないディスクは大部分がzerofillされている。2TBのディスクのうち、データが書かれているのは4GB、なんてことがあるわけだ。
しかも、1TBとか2TBとかサイズがあるので、なるべく高速に処理したい。 速度を重視しつつ、非常に小さいサイズに抑えられるのが理想。
一覧表
Ryzen5 5600X (6C12T)のSchedutilsで計測した。 メモリはDDR4-3200で32GB。
ソースは1GiBのzerofillされたファイル。
command | options | time | size | ratio |
---|---|---|---|---|
gzip |
-1 -c |
2.313 | 4583762 | 0.004476 |
bzip2 |
-1 -c |
4.645 | 6533 | 0.000006 |
xz |
-0 -c |
5.101 | 156316 | 0.000153 |
xz |
-0 -c -T0 |
0.582 | 263200 | 0.000257 |
lz4 |
-1 -c |
0.630 | 4214543 | 0.004116 |
zstd |
-c --zstd=strategy=1 |
0.380 | 33679 | 0.000033 |
zstd |
-c -T0 --zstd=strategy=1 |
0.379 | 33679 | 0.000033 |
zstd |
-c --format=lz4 |
1.699 | 4423696 | 0.004320 |
zstd |
-c -T0 --format=lz4 |
1.697 | 4423696 | 0.004320 |
コメント
gzip/lz4はでかい
無難そうなgzipやlz4は、サイズが突出して大きい。
gzipは速くもない。
bzip2は小さいが遅い
bzip2は突出して小さい。
だが、かなり遅く、時間をかけて丁寧に圧縮している感じ。 それでもシングルスレッドxzよりは速く、xzより小さい。
xzは-T0なら速いが、サイズは大きくなる
-T0した場合、ほとんどスレッド数に比例して高速化できる。 もっとコア数の多いCPUなら最速だろう。
しかし、かなりサイズは増えている。 スレッド間でソースの情報を共有していないためだろう。
ただ、同じ割合だとすると、1TBに対して260MBほど。十分小さいため、速度重視ならxz -0 -T0
はアリかもしれない。
zstdの-Tは無意味?
zstdの場合、-T0
しても速度的にもサイズ的にも変化がない。
効いてないのかとも思ったが、ソースを見てワーカーにオフロードするため、zerofill部分は並列にならないのかもしれない。
この結果ではzstdのstrategy=1
が最速だが、CPUコア数が増えればxz -T0
が逆転しそう。
zstdのlz4はいいとこなし
遅い上に大きい。
zstdはzstdのために使うのが良さそうだが、並列化が効くなら話は少し変わってくる可能性もある。
ただ、それでも--zstd=strategy=1
のほうが速そうなので、あまり他の選択肢は候補にはならないように思える。
実際にやってみた所感
そもそもこのテストをするに至った動機でもあるが、新しいラップトップが手元に届いたので、「Windows 11 Homeがプリインストールされた、まっさらな状態の512GB SSD」を圧縮保存してみた。
zstd -c --zstd-strategy=1
はCore i7-1360P (Raptor
Lake-P)のモバイルラップトップでも100%なんてとても届かない使用率だったため、生で転送してデスクトップ側で圧縮するよりも、ラップトップ側で圧縮してデスクトップ側は保存するだけのほうが転送量が減少して高速であった。
ただ、ファイルサイズは期待ほど小さくならず、最終的には31078190650
バイトとなった。
だいたい1/16で、あまり満足のいく結果ではない。
試しに
unzstd -c < file.img.zst | bzip2 -1 -c > file.img.bz2
してみたところ、最終的なサイズは31889672357
バイトとむしろ増加してしまった。
zstdの場合はコンスタントに容量が増加し続けていたのに対し、bzip2では容量がほとんど増加しない時間があったため、zerofill部分の圧縮に関しては先の実験の通りの結果が得られているように思う。 しかし、データ圧縮に関してはzstdのほうが優れているのか、この再圧縮は報われなかった。
なお、所要時間は1:51:20であり、結構長い。
Windows 10 Homeの入っていたIdeaPad Slim 360
(17)のxz -e
の結果が8797336184
バイト、Windows
10 Professionalが入っていたThinkPad X1 Carbon
Gen6の結果が7791701089
バイトであることを考えると随分大きい。
これは、Windows
11が大幅に膨張したのかもしれないし、Dynabookだから色々余計なものが入っていてデータサイズが大きいのかもしれない。
データサイズ削減を主眼において
unzstd -c < file.img.zst | xz -e -c -T0 > file.img.bz2
も試してみたところ、非常に多くのCPUリソースを費やしたが、28996113836
と削減幅は2GB程度だった。
このDynabook特有の事情がある可能性もあるが、所要時間を飲んでzstd→bzip2に変更する価値はなさそうだ。
結論
zerofillデータの圧縮そのものはbzipが容量面では優れている。
速度ではコア数が多い環境なら最速はおそらくxz -0 -T0
だが、サイズも加味して考えるならzstd --zstd=strategy=1
がベストっぽい。
初期ディスクのダンプしいう観点では、転送元(新品ラップトップ)側でzstdで圧縮して転送するのが一番早そうだ。
実際はデータも絡むため、zerofill圧縮率に優れたbzip2に圧縮し直すのは微妙。 というよりも、zstdが結構優秀で、互換性の問題を除けばbzip2を使う理由はなさそう。
XZを採用するかという意味では、-e
オプションまでつければ多少データサイズの節約にはなるが、得られるものは小さいので、本当に少しでもサイズを小さくしたいという場合のみか。