🗜️

圧縮ツールの比較: gzip, bzip2, lzop, lz4, xz, zstd

2024/04/06に公開

Linux環境でよく使われている圧縮ツールの性能を知っておきたかったので、圧縮率や処理時の負荷などを評価した。

評価の目的は、データを圧縮して保存したりそれを伸長して使ったりする際に、どれが有用なのかということ。

評価対象

評価対象のツールは下記の6種類とした。バージョンはいずれもDebian 12 (bookworm) for AMD64で標準のもの。

名前 バージョン
GNU Gzip 1.12
bzip2 1.0.8
LZO 1.04
LZ4 1.9.4
XZ Utils 5.4.1
Zstandard (zstd) 1.5.4
  • XZ Utilsのリンク先は、記事作成時点ではバックドア対応のため工事中

評価条件

  • 圧縮対象のデータ: テキストデータとバイナリデータをそれぞれ1つずつ
    • テキストデータ: Linuxカーネルのソースコード
    • バイナリデータ: Ubuntuのdebパッケージ
    • 補足
      • 追試しやすいよう、再入手が容易なものとした
      • 保存用途での評価をしたかったので、ある程度大きなデータを選んだ
  • 実行環境
    • プロセッサ: Intel Core i7-5600U (最大動作周波数 3.2 GHz)
    • メモリ: 8 MB
    • OS: Debian 12 (bookworm) for AMD64

評価結果

テキストデータ

Linuxカーネルのソースコード linux-5.15.153.tar (約1GiB) での測定結果。

コマンド名 圧縮率 [%] 圧縮時間 [sec] 圧縮時スループット [MiB/sec] 圧縮時メモリ [KiB] 伸長時間 [sec] 伸長時スループット [MiB/sec] 伸長時メモリ [KiB]
gzip 17.44 30.72 6.17 1,968 5.31 204.73 1,652
bzip2 13.11 85.79 1.66 8,584 23.66 45.95 4,904
lzop 29.71 2.41 134.04 2,144 2.19 496.41 1,788
lz4 28.67 2.44 127.73 8,728 0.94 1,156.52 9,284
xz 11.10 387.46 0.31 97,588 8.66 125.53 10,288
zstd 16.19 5.58 31.54 44,836 1.45 749.74 5,460
  • 圧縮率の良さならxzがよい
  • 圧縮時間の短さならlzop・lz4がよい
  • 圧縮時スループットの高さならlzop・lz4がよい
  • 伸長時間の短さならlz4・zstdがよい
  • 伸長時スループットの高さならlz4・zstdがよい
  • 圧縮・伸長時の最大メモリ使用量は、PCやサーバであれば、どれでも十分に小さいため大した負荷にならないと思われる
  • 圧縮率・圧縮時間・伸長時間すべてにおいて、gzipよりもzstdのほうがよい

データを圧縮して保存する用途には、圧縮率を良くしたいならxzが、圧縮率は程々でいいので時間を短く済ませたいならzstdがよさそう。

各測定値の補足
  • 各コマンドでの圧縮や伸長はデフォルトのまま実施
  • 圧縮率: 非圧縮データサイズに対する圧縮データサイズの比率
  • 圧縮時間: 非圧縮データを圧縮したときの所要時間
  • 圧縮時スループット: 圧縮時の単位時間あたりの圧縮後サイズ
  • 圧縮時メモリ: 非圧縮データを圧縮したときの最大メモリ使用量
  • 伸長時間: 圧縮データを伸長したときの所要時間
  • 伸長時スループット: 伸長時の単位時間あたりの伸長後サイズ
  • 伸長時メモリ: 圧縮データを伸長したときの最大メモリ使用量

バイナリデータ

Ubuntu 22.04 LTSのlinux-modules-extraパッケージの伸長後のデータ部分(約340MiB)での測定結果。

コマンド名 圧縮率 [%] 圧縮時間 [sec] 圧縮時スループット [MiB/sec] 圧縮時メモリ [KiB] 伸長時間 [sec] 伸長時スループット [MiB/sec] 伸長時メモリ [KiB]
gzip 27.85 15.88 5.90 1,892 2.14 63.37 1,708
bzip2 22.55 19.60 3.87 8,596 8.92 14.22 4,972
lzop 40.35 0.86 157.85 2,144 0.69 153.64 1,780
lz4 40.39 0.78 174.22 8,720 0.31 357.95 8,984
xz 16.22 151.72 0.36 97,524 4.22 38.85 10,348
zstd 23.10 1.99 39.05 45,904 0.54 232.05 5,508
  • 傾向はテキストデータの場合とほぼ同一
  • 今回使用したデータでは、テキストデータのほうがバイナリデータよりも圧縮率が良く伸長時スループットが高い
  • 圧縮・伸長時の最大メモリ使用量はテキストデータの場合とほぼ同一値 (データの種別やサイズによらないと捉えてよさそう)

測定に関する補足

  • 最大メモリ使用量を測定するために、シェルのビルトインの time ではなく /usr/bin/time コマンドを使用した
  • ストレージ入出力による速度低下を避けるため、実行はtmpfs上で行った

使用したスクリプトは下記のとおり。コマンドライン引数に非圧縮ファイル名を並べて実行する。

使用したスクリプト
#! /bin/sh

if [ $# -eq 0 ]; then
  echo 'No files specified' 1>&2
  exit 1
fi

trap '
  exit_status="$?"
  test -f compressed && rm compressed
  exit "$exit_status"
' EXIT
trap 'exit 1' HUP INT TERM

for file in $*; do
  data_original_size=`stat --format='%s' $file`
  for cmd_set in \
    'gzip:zcat' \
    'bzip2:bzcat' \
    'lzop:lzop -d' \
    'lz4:lz4cat' \
    'xz:xzcat' \
    'zstd:zstdcat' \
  ; do
    cmd_compress=`echo $cmd_set | cut -d: -f1`
    cmd_decompress=`echo $cmd_set | cut -d: -f2`
    $cmd_compress < $file > compressed
    data_compressed_size=`stat --format='%s' compressed`
    data_compress_ratio=`echo "${data_compressed_size} / ${data_original_size}" | bc -l`
    data_tmp=`/usr/bin/time --format '%U,%M' $cmd_compress < $file 2>&1 >/dev/null`
    data_compress_time=`echo $data_tmp | cut -d, -f1`
    data_compress_rss=`echo $data_tmp | cut -d, -f2`
    data_compress_throughput=`echo "${data_compressed_size} / (1024 * 1024) / ${data_compress_time}" | bc -l`
    data_tmp=`/usr/bin/time --format '%U,%M' $cmd_decompress < compressed 2>&1 >/dev/null`
    data_decompress_time=`echo $data_tmp | cut -d, -f1`
    data_decompress_rss=`echo $data_tmp | cut -d, -f2`
    data_decompress_throughput=`echo "${data_original_size} / (1024 * 1024) / ${data_decompress_time}" | bc -l`
    rm -f compressed
    echo "${file},${cmd_compress},${data_compress_ratio},${data_compress_time},${data_compress_throughput},${data_compress_rss},${data_decompress_time},${data_decompress_throughput},${data_decompress_rss}"
  done
done

参考文献

Discussion