みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

マルチスレッド環境でのtar

最近ではCPUはマルチコアであることが多く、プログラムがマルチスレッドに対応している場合、 処理時間を大幅に短縮することができる。

意外と機会の多いtarコマンドによる圧縮伸長処理はデフォルトではシングルスレッドで動作するため、 マルチコアCPUの恩恵が受けられない。

tarコマンドがマルチコアCPUの恩恵を受けるための方法を調べた。

従来の方法

tar使用時の圧縮形式とオプションについては次の表のようになる。

圧縮形式 拡張子 圧縮 伸長 圧縮率 処理時間 備考
GZIP tar.gz cfz xf
BZIP2 tar.bz2 cfj xf
XZ(LZMA2) tar.xz cfJ xfJ 1.22からサポート

大体、vオプションを含んで実行することが多いため、コマンドの実行例は次のようになる。

$ tar cvfz HOGE.tar.gz ./HOGE

マルチスレッド対応の圧縮コマンド

tarで指定できる形式で、マルチスレッド対応の圧縮伸張コマンドが存在する。

圧縮形式 圧縮伸張コマンド
GZIP pigz
BZIP2 pbzip2
XZ(LZMA2) pxz/pixz

pxzとpixz

pixzはxzを圧縮する際にインデックス情報を保持させることができる。 インデックスを参照ことで、アーカイブから一部のファイルだけ取り出す場合に全体を展開する必要がなくなる。

pixzで作成したアーカイブもxzやpxzで伸張することができるが、その場合インデックスは意味をなさない。

インストール方法

Ubuntuであればaptでインストールできる

$ sudo apt install pigz pzip2 pxz

tarのオプション

tarでは-Iもしくは--use-compress-programで圧縮伸張に使用するコマンドを指定する事ができる。

tarで指定する場合は次のようなオプションとなる。

圧縮形式 拡張子 圧縮オプション 伸張
GZIP tar.gz -I pigz -cf -I pigz -xf
BZIP2 tar.bz2 -I pbzip2 -cf -I pbzip2 -xf
XZ(pxz) tar.xz -I pxz -cf -I pxz -xf
XZ(pixz) tar.xz -I pixz -cf -I pixz -xf

実行例(GZIP)

圧縮

$ tar -I pigz -cf HOGE.tar.gz ./HOGE

伸張

$ tar -I pigz -xf HOGE.tar.gz

実行例(BZIP2)

圧縮

$ tar -I pbzip2 -cf HOGE.tar.bz2 ./HOGE

伸張

$ tar -I pbzip2 -xf HOGE.tar.bz2

実行例(XZ/pxz)

圧縮

$ tar -I pxz -cf HOGE.tar.xz ./HOGE

伸張

$ tar -I pxz -xf HOGE.tar.xz

実行例(XZ/pixz)

圧縮

$ tar -I pixz -cf HOGE.tar.xz ./HOGE

伸張

$ tar -I pixz -xf HOGE.tar.xz

性能比較

timeコマンドによって時間を計測した。

timeコマンドではrealusersysの3つの時間が表示される。 これらの値は次のような意味を持っている。

概要 備考
real コマンドを開始してから終了するまでの時間
user ユーザープログラムのCPU使用時間 アプリやライブラリ
sys システムのCPU使用時間 カーネル

処理が正しく並列に実行されている場合は、実際に処理にかかる時間(real)よりもプログラムのCPU使用時間(user)の方が大きくなる。

圧縮性能

シングル マルチ シングル(msec) マルチ(msec)
GZIP real 0m37.454s 0m4.495s 37454 4495
user 0m24.996s 0m31.620s 24996 31620
sys 0m1.676s 0m1.104s 1676 1104
BZIP2 real 1m39.269s 0m31.026s 99269 31026
user 1m37.900s 3m44.148s 97900 224148
sys 0m1.384s 0m3.836s 1380 3836
XZ(pxz) real 4m34.652s 0m49.782s 274652 49782
user 4m33.948s 5m48.872s 273948 348872
sys 0m2.600s 0m3.392s 2600 3392
XZ(pixz) real - 0m46.958s - 46958
user - 5m42.244s - 342244
sys - 0m2.120s - 2120

マルチスレッド版はどのコマンドでもreal < userとなり、並列に処理されていることがわかる。

realの時間を比較しても、高速に処理されていることがわかる。

圧縮に関しては、pxzとpixzで大きな差は見られなかった。

伸張性能

シングル マルチ シングル(msec) マルチ(msec)
GZIP real 0m4.498s 0m2.272s 4498 2272
user 0m4.268s 0m2.740s 4268 2740
sys 0m0.936s 0m1.056s 936 1056
BZIP2 real 0m42.598s 0m11.781s 42598 11781
user 0m41.976s 1m29.540s 41976 89540
sys 0m1.612s 0m1.144s 1612 1144
XZ(pxz) real 0m25.418s 0m25.817s 25418 25817
user 0m25.140s 0m24.984s 25140 24984
sys 0m1.988s 0m1.892s 1988 1892
XZ(pixz) real - 0m5.744s - 5744
user - 0m32.068s - 32068
sys - 0m1.352s - 1352

圧縮と比較するとシングルスレッド版でもそれほど時間がかからないので、差は小さくみえる。

pigzとpbzip2に関しては並列に処理されているが、pxzに関しては何故かシングルスレッドで動作しているようだった。 pixzでは狙い通りマルチスレッドで動作されているため、高速に処理されていることがわかる。

このためUbuntu16.04では、xz形式のファイルで並列処理したい場合は、pxzよりもpixzの方がよさそう。

結論

pxzコマンド以外は、マルチスレッド対応のコマンドを使用することで大幅に処理時間を短縮できることが解った。 意外とtarでの圧縮伸張はする機会が多いため、これらを有効に活用することで作業時間を短縮できる。