tar コマンドの圧縮オプション比較

tar コマンドではアーカイブと同時に圧縮することが出来ます。昔は gzip しか使えませんでしたが、今は bzip2/xz も使うことが出来ます。そこで、それぞれの圧縮方法で実際にどれくらい圧縮効率と圧縮/展開時間が違うのか比較してみました。

## 実験環境

実験した環境は FreeBSD 11.4-RELEASE-p4 で、tar コマンドのバージョンは 3.4.2 です。

使用したデータはウィキペディア日本語版のデータベースダンプです。2020年11月1日版で 13584231059 バイト(13 GiB)ありました。

```shell
$ curl -O https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2
$ bzip2 -d jawiki-latest-pages-articles.xml.bz2
$ ls -l jawiki-latest-pages-articles.xml
-rw-r--r--  1 saoyagi2 staff  13584231059 11月 11 09:48 jawiki-latest-pages-articles.xml
```

## 実験

### gzip

```shell
$ /usr/bin/time tar czf jawiki-latest-pages-articles.xml.tar.gz jawiki-latest-pages-articles.xml
      852.37 real       826.38 user        24.54 sys
$ ls -l jawiki-latest-pages-articles.xml.tar.gz
-rw-r--r--  1 saoyagi2  staff  4366160632 11月 12 12:11 jawiki-latest-pages-articles.xml.tar.gz
$ /usr/bin/time tar xf jawiki-latest-pages-articles.xml.tar.gz
      175.45 real        82.09 user        20.99 sys
```

### bzip2

```shell
$ /usr/bin/time tar cjf jawiki-latest-pages-articles.xml.tar.bz2 jawiki-latest-pages-articles.xml
     2313.50 real      2289.61 user        21.92 sys
$ ls -l jawiki-latest-pages-articles.xml.tar.bz2
-rw-r--r--  1 saoyagi2  staff  3235179785 11月 12 12:53 jawiki-latest-pages-articles.xml.tar.bz2
$ /usr/bin/time tar xf jawiki-latest-pages-articles.xml.tar.bz2
     1073.77 real      1044.34 user        27.68 sys
```

### xz

```shell
$ /usr/bin/time tar cJf jawiki-latest-pages-articles.xml.tar.xz jawiki-latest-pages-articles.xml
    13596.21 real     13561.03 user        28.69 sys
$ ls -l jawiki-latest-pages-articles.xml.tar.xz
-rw-r--r--  1 saoyagi2  staff  2787826328 11月 12 16:57 jawiki-latest-pages-articles.xml.tar.xz
$ /usr/bin/time tar xf jawiki-latest-pages-articles.xml.tar.xz
      350.36 real       327.34 user        21.27 sys
```

## まとめと考察

| 圧縮方法 | 圧縮時間(user + sys) | 展開時間(user + sys) | 圧縮後サイズ | 圧縮率 |
|---|---|---|---|---|
| gzip | 850.92 秒| 103.08 秒 | 4366160632 バイト(4.1 GiB) | 32.14% |
| bzip2 | 2311.53 秒 | 1072.02 秒 | 3235179785 バイト(3.0 GiB) | 23.81% |
| xz | 13589.72 秒 | 348.61 秒 | 2787826328 バイト(2.6 GiB)| 20.52% |

傾向としては、

* 圧縮時間は gzip < bzip2 < xz
* 展開時間は gzip < xz < bzip2
* 圧縮率は xz < bzip2 < gzip

となりました。もちろんファイルの内容によっていずれも変わってきますので、必ずこの順位になるとは限りません。~~また、tar のオプションではなく各圧縮コマンドを独立して使用する場合には圧縮率のオプションを指定できますので、さらに傾向が変わる可能性があります。~~(圧縮レベル指定についての追記参照)

この傾向から判断するとすると

* gzip - そこそこ圧縮率で圧縮時間・展開時間とも最速。ファーストチョイスとして最適。
* bzip2 - xz よりも短い圧縮時間で gzip よりも高圧縮率を得られる。展開は遅い。長期保存するログなど、めったに展開しない用途に向いている。
* xz - 圧縮には膨大な時間がかかるが展開時間は高速で圧縮率も良い。一度だけ圧縮して何度も展開されるファイル配布などの用途に向いている。

といったところでしょうか。実験を始める前は gzip はそろそろ退役してよいのかなと思っていたのですが、なんのなんのファーストチョイスとしては今でも間違いなさそうです。

## 圧縮レベル指定についての追記(2020.11.23)

環境変数やオプションによって tar コマンド単体でも圧縮レベルを指定できることを知りました。例えば以下のようにします。

```shell
$ export GZIP=-9
$ tar czf jawiki-latest-pages-articles.xml.tar.gz jawiki-latest-pages-articles.xml
$ export BZIP2=-9
$ tar cjf jawiki-latest-pages-articles.xml.tar.bz2 jawiki-latest-pages-articles.xml
$ export XZ_OPT=-9
$ tar cJf jawiki-latest-pages-articles.xml.tar.xz jawiki-latest-pages-articles.xml
```

ただし、gzip の最近のバージョン(1.8以降?)では GZIP 環境変数は廃止されたそうなのですが、手元の Ubuntu 20.04 LTS 環境では `gzip: warning: GZIP environment variable is deprecated; use an alias or script` とメッセージは出るものの、まだ GZIP 環境変数は機能していました。gzip のバージョンは 1.10 でした。

FreeBSD の tar では GZIP のみならず BZIP2 も XZ_OPT も効かなくなっていました。FreeBSD では代わりに compression-level オプションで圧縮レベルを指定できます。

```shell
$ tar czf jawiki-latest-pages-articles.xml.tar.gz --options gzip:compression-level=9 jawiki-latest-pages-articles.xml
$ tar cjf jawiki-latest-pages-articles.xml.tar.bz2 --options bzip2:compression-level=9 jawiki-latest-pages-articles.xml
$ tar cJf jawiki-latest-pages-articles.xml.tar.xz --options xz:compression-level=9 jawiki-latest-pages-articles.xml
```