gzip/bzip2/xzの圧縮レベル比較

[tar コマンドの圧縮オプション比較](https://qiita.com/saoyagi2/items/2f6a20640d6ae541afdc) で tar コマンドでの圧縮オプションの比較を行いましたが、各圧縮コマンドでは圧縮レベルを指定できます。

普段は「速く終わって欲しいから `-1`」とか「とにかく小さくして欲しいので `-9`」とかくらいの気分で指定しているのですが、実際のところどれくらい圧縮率と圧縮/展開速度に違いがあるのか試してみました。

## 実験環境

前回に引き続き FreeBSD 11.4-RELEASE-p4 で実験を行い、対象データは2020年11月1日版のウィキペディア日本語版データベースダンプ(pages-articles)を使用しました。サイズは 13584231059 バイト(13 GiB)です。

各コマンドのバージョンは以下の通りです。

```shell
$ gzip -V
FreeBSD gzip 20190107
$ bzip2 -V
bzip2, a block-sorting file compressor.  Version 1.0.8, 13-Jul-2019.

   Copyright (C) 1996-2019 by Julian Seward.

   This program is free software; you can redistribute it and/or modify
   it under the terms set out in the LICENSE file, which is included
   in the bzip2 source distribution.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   LICENSE file for more details.

$ xz -V
xz (XZ Utils) 5.2.5
liblzma 5.2.5
```

## 実験内容

### gzip

```shell
$ /usr/bin/time gzip -1 jawiki-latest-pages-articles.xml
      355.36 real       330.50 user        23.22 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  5090855208 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      180.56 real       109.98 user        22.01 sys

$ /usr/bin/time gzip -2 jawiki-latest-pages-articles.xml
      384.12 real       359.09 user        23.45 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  4910715932 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      180.67 real       106.66 user        21.53 sys

$ /usr/bin/time gzip -3 jawiki-latest-pages-articles.xml
      445.48 real       421.68 user        22.05 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  4757662603 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      177.84 real       105.21 user        20.60 sys

$ /usr/bin/time gzip -4 jawiki-latest-pages-articles.xml
      530.53 real       507.04 user        21.96 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  4555013197 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      176.09 real       101.52 user        20.01 sys

$ /usr/bin/time gzip -5 jawiki-latest-pages-articles.xml
      669.78 real       646.16 user        21.93 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  4425196667 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      177.01 real        99.00 user        20.09 sys

$ /usr/bin/time gzip -6 jawiki-latest-pages-articles.xml
      850.59 real       827.41 user        21.52 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  4366161410 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      174.15 real        97.89 user        20.16 sys

$ /usr/bin/time gzip -7 jawiki-latest-pages-articles.xml
      915.27 real       891.61 user        21.96 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  4358354797 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      177.45 real        98.17 user        19.50 sys

$ /usr/bin/time gzip -8 jawiki-latest-pages-articles.xml
      980.19 real       956.30 user        22.14 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  4353562879 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      175.12 real        98.04 user        21.08 sys

$ /usr/bin/time gzip -9 jawiki-latest-pages-articles.xml
      986.73 real       963.48 user        21.52 sys
$ ls -l jawiki-latest-pages-articles.xml.gz
-rw-r--r--  1 shigekazu  staff  4353452382 11月 19 06:26 jawiki-latest-pages-articles.xml.gz
$ /usr/bin/time gzip -d jawiki-latest-pages-articles.xml.gz
      176.77 real        98.06 user        19.58 sys
```

### bzip2

```shell
$ /usr/bin/time bzip2 -1 jawiki-latest-pages-articles.xml
     1852.66 real      1819.48 user        31.03 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3821671994 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
      654.93 real       629.23 user        24.26 sys

$ /usr/bin/time bzip2 -2 jawiki-latest-pages-articles.xml
     1909.93 real      1882.62 user        25.64 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3599052964 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
      789.60 real       760.91 user        26.99 sys

$ /usr/bin/time bzip2 -3 jawiki-latest-pages-articles.xml
     2111.15 real      2085.68 user        23.80 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3488798993 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
      790.16 real       761.34 user        27.25 sys

$ /usr/bin/time bzip2 -4 jawiki-latest-pages-articles.xml
     2096.57 real      2072.32 user        22.58 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3417182323 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
      870.70 real       843.33 user        26.10 sys

$ /usr/bin/time bzip2 -5 jawiki-latest-pages-articles.xml
     2188.89 real      2164.86 user        22.42 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3364498463 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
      920.75 real       892.67 user        26.65 sys

$ /usr/bin/time bzip2 -6 jawiki-latest-pages-articles.xml
     2215.03 real      2191.58 user        21.75 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3323241746 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
      973.09 real       944.87 user        26.86 sys

$ /usr/bin/time bzip2 -7 jawiki-latest-pages-articles.xml
     2237.27 real      2213.98 user        21.62 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3288781109 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
     1015.46 real       986.67 user        27.49 sys

$ /usr/bin/time bzip2 -8 jawiki-latest-pages-articles.xml
     2326.10 real      2303.06 user        21.03 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3260033347 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
     1047.87 real      1018.74 user        27.64 sys

$ /usr/bin/time bzip2 -9 jawiki-latest-pages-articles.xml
     2376.22 real      2352.21 user        21.76 sys
$ ls -l jawiki-latest-pages-articles.xml.bz2
-rw-r--r--  1 shigekazu  staff  3235159003 11月 19 06:26 jawiki-latest-pages-articles.xml.bz2
$ /usr/bin/time bzip2 -d jawiki-latest-pages-articles.xml.bz2
     1080.97 real      1052.71 user        26.95 sys
```

### xz

```shell
$ /usr/bin/time xz -0 jawiki-latest-pages-articles.xml
     1645.98 real      1613.18 user        30.01 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  4056325252 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      485.17 real       452.28 user        31.24 sys

$ /usr/bin/time xz -1 jawiki-latest-pages-articles.xml
     2358.35 real      2320.87 user        35.58 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  3626872136 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      429.68 real       398.58 user        29.64 sys

$ /usr/bin/time xz -2 jawiki-latest-pages-articles.xml
     3757.15 real      3715.57 user        39.02 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  3448516804 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      410.21 real       379.19 user        29.32 sys

$ /usr/bin/time xz -3 jawiki-latest-pages-articles.xml
     6130.79 real      6086.97 user        40.28 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  3330256732 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      399.45 real       367.28 user        30.85 sys

$ /usr/bin/time xz -4 jawiki-latest-pages-articles.xml
     8759.58 real      8706.89 user        48.18 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  3051961880 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      382.95 real       352.47 user        29.04 sys

$ /usr/bin/time xz -5 jawiki-latest-pages-articles.xml
    12283.70 real     12228.49 user        49.17 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  2835451316 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      361.88 real       331.16 user        29.19 sys

$ /usr/bin/time xz -6 jawiki-latest-pages-articles.xml
    13660.40 real     13604.44 user        49.41 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  2787827176 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      358.19 real       327.56 user        29.30 sys

$ /usr/bin/time xz -7 jawiki-latest-pages-articles.xml
    15521.95 real     15465.83 user        48.68 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  2694548072 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      348.99 real       318.49 user        29.13 sys

$ /usr/bin/time xz -8 jawiki-latest-pages-articles.xml
    17470.23 real     17411.22 user        50.24 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  2608697716 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      343.91 real       311.68 user        28.23 sys

$ /usr/bin/time xz -9 jawiki-latest-pages-articles.xml
    19416.77 real     19357.10 user        50.10 sys
$ ls -l jawiki-latest-pages-articles.xml.xz
-rw-r--r--  1 shigekazu  staff  2530386528 11月 19 06:26 jawiki-latest-pages-articles.xml.xz
$ /usr/bin/time xz -d jawiki-latest-pages-articles.xml.xz
      334.49 real       303.25 user        29.58 sys
```

## まとめと考察

| 圧縮方法とレベル | 圧縮時間(user + sys) | 展開時間(user + sys) | 圧縮後サイズ | 圧縮率 |
|-----------|------------:|------------:|------------:|------------:|
| gzip(-1) | 353.72 秒 | 131.99 秒 | 5090855208 バイト | 37.47% |
| gzip(-2) | 382.54 秒 | 128.19 秒 | 4910715932 バイト | 36.15% |
| gzip(-3) | 443.73 秒 | 125.81 秒 | 4757662603 バイト | 35.02% |
| gzip(-4) | 529.00 秒 | 121.53 秒 | 4555013197 バイト | 33.53% |
| gzip(-5) | 668.09 秒 | 119.09 秒 | 4425196667 バイト | 32.57% |
| gzip(-6) | 848.93 秒 | 118.05 秒 | 4366161410 バイト | 32.14% |
| gzip(-7) | 913.57 秒 | 117.67 秒 | 4358354797 バイト | 32.08% |
| gzip(-8) | 978.44 秒 | 119.12 秒 | 4353562879 バイト | 32.04% |
| gzip(-9) | 985.00 秒 | 117.64 秒 | 4353452382 バイト | 32.04% |
| bzip2(-1) | 1850.51 秒 | 653.49 秒 | 3821671994 バイト | 28.13% |
| bzip2(-2) | 1908.26 秒 | 787.90 秒 | 3599052964 バイト | 26.49% |
| bzip2(-3) | 2109.48 秒 | 788.59 秒 | 3488798993 バイト | 25.68% |
| bzip2(-4) | 2094.90 秒 | 869.43 秒 | 3417182323 バイト | 25.15% |
| bzip2(-5) | 2187.28 秒 | 919.32 秒 | 3364498463 バイト | 24.76% |
| bzip2(-6) | 2213.33 秒 | 971.73 秒 | 3323241746 バイト | 24.46% |
| bzip2(-7) | 2235.60 秒 | 1014.16 秒 | 3288781109 バイト | 24.21% |
| bzip2(-8) | 2324.09 秒 | 1046.38 秒 | 3260033347 バイト | 23.99% |
| bzip2(-9) | 2373.97 秒 | 1079.66 秒 | 3235159003 バイト | 23.81% |
| xz(-0) | 1643.19 秒 | 483.52 秒 | 4056325252 バイト | 29.86% |
| xz(-1) | 2356.45 秒 | 428.22 秒 | 3626872136 バイト | 26.69% |
| xz(-2) | 3754.59 秒 | 408.51 秒 | 3448516804 バイト | 25.38% |
| xz(-3) | 6127.25 秒 | 398.13 秒 | 3330256732 バイト | 24.51% |
| xz(-4) | 8755.07 秒 | 381.51 秒 | 3051961880 バイト | 22.46% |
| xz(-5) | 12277.66 秒 | 360.35 秒 | 2835451316 バイト | 20.87% |
| xz(-6) | 13653.85 秒 | 356.86 秒 | 2787827176 バイト | 20.52% |
| xz(-7) | 15514.51 秒 | 347.62 秒 | 2694548072 バイト | 19.83% |
| xz(-8) | 17461.46 秒 | 339.91 秒 | 2608697716 バイト | 19.20% |
| xz(-9) | 19407.20 秒 | 332.83 秒 | 2530386528 バイト | 18.62% |

全体の傾向として、
* 圧縮展開とも最速でそこそこの圧縮率の gzip
* 圧縮時間そこそこで展開が遅い bzip2
* 圧縮時間が長大で圧縮率が高い xz
は変わりません。

圧縮率の最大と最低で入れ替わりが頻繁に起こるかなと思ったのですが、bzip2 と xz の一部で起こったくらいでした。

各コマンド共に共通しているのは、圧縮レベルを上げると圧縮時間が単調に増加し、圧縮率は単調に減少していることです。また、圧縮レベルが違うのに圧縮率が同じになることがありませんでしたので、圧縮レベルの指定は実際の挙動にしっかりと影響を与えていました。それなりに大きなファイルを使っての結果ですので、小さなファイルでは圧縮率が同じになってしまうケースもあるかと思われます。

意外だったのは gzip と xz で圧縮レベルをあげるほどに展開時間が短くなっていく傾向があることでした。ファイルサイズが小さくなることでディスク I/O が軽減することと、データサイズが小さくなって CPU キャッシュのヒット率があがることが原因ではないかと想像します。