はじめに
最近、Inflate 実装のチューニングを行うことが多かったので、現状でどの程度の速度が出ているか把握するため、他の実装と比較してみました。
比較に使用した ZLIB ライブラリ
今回の比較では、以下のライブラリの存在を確認しています。 uncompress.js に関しては、今回入手できなかったため比較対象からはずしています。
名前 | Input | Output | 名前空間 | ライセンス | ファイルサイズ |
---|---|---|---|---|---|
pdf.js | Uint8Array, Array, ArrayBuffer(*) |
Uint8Array | FlateStream, Stream, DecodeStream, etc... |
MIT | stream.js: 80,349 |
zlib-js | String | String | ZLIB | zlib | zlib-inflate.js: 86,884 zlib.js: 4,893 |
zlib.js | Uint8Array, Array |
Uint8Array, Array |
Zlib | MIT | inflate.min.js: 13,222 |
uncompress.js | Uint8Array, Array |
Uint8Array, Array |
zlib | zlib | uncompress.min.js: 11,843 |
jsziptools | Uint8Array, Array, String, ArrayBuffer |
ArrayBuffer | jz | MIT | jsziptools.min.js: 10,536(*) dataview.min.js: 3,189 |
zpipe | String | String | zpipe | zlib? | zpipe.min.js: 206,267 |
各ライブラリの簡単な特徴
pdf.js | Typed Array のサポートが必要。 |
---|---|
zlib-js | Typed Array 未サポートの環境でも使用可能。 zlib の移植。 |
zlib.js | Typed Array 未サポートの環境でも使用可能。 Stream 版(逐次展開)実装あり。 strict mode 対応。 Node.js 版あり。 Closure Library 対応。 出力バッファサイズの指定可能。 |
uncompress.js | Typed Array 未サポートの環境でも使用可能。 zlib 1.2.5 の移植。 strict mode 対応。 出力バッファ指定可能。 現在サイトにつながらない? |
jsziptools | PKZIP 対応。 Typed Array のサポートが必要。 Inflate 実装は pdf.js の実装を使用。 ffDataView が必要。 |
zpipe | zlib ライブラリに添付されている zpipe.c を emscripten で移植したもの。 Typed Array のサポートが必要。 Node.js 版あり。 |
分類について
見た感じ、大きく分けて3種類に分類することが出来ます。
- zlib 移植系
- zlib-js
- uncompress.js
- zpipe
- pdf.js 系
- pdf.js
- jsziptools
- 独自実装系
- zlib.js
FlateStream について
FlateStream の入力は同じ stream.js 内で定義されている Stream のオブジェクトです。
new FlateStream(new Stream(array))
のような形で使います。array は Uint8Array のコンストラクタに渡せるものならば何でも OK です。
FlateStream を利用しているライブラリでは、この Stream を直接使うのではなく、getBytes メソッドを呼ぶ部分のコードを削って Uint8Array をそのまま渡すようにしていることが多いようです。
ビルドについて
ビルドスクリプトなどがついていて、Inflate の比較においてサイズ削減が可能なものに関してはすべて最低限で行っています。
jsziptools
jsziptools はビルドスクリプトが添付されていて、必要な実装のみでビルドすることが可能です。
今回は以下のようにして、zlib 伸張のみでビルドしました。
$ python build.py -m zlib.decompress
zlib.js
zlib.js では全ての実装を分離してビルドすることが出来、リポジトリの bin ディレクトリにそれぞれのファイルが生成されています。
今回は ZLIB の伸張なので inflate.min.js と inflate_stream.min.js をそのまま利用しています。
比較条件
速度比較に利用したデータ
http://www.compression.ca/act/act-files.html で使用しているデータの中からいくつかを Node.js の Zlib でデフォルト設定のまま圧縮したものです。
また、画像に関しては HTML5 Logo (PNG) から IDAT チャンクを抜き出したものを使用しています。
それぞれのライブラリで入力データの形式が違うので、データは予め String, Array, Uint8Array それぞれの形式に変換し、最も速度の出るものを利用しています。(純粋に伸張処理にかかった時間で比較しています。)
実際にライブラリで使用する際には、対応していない入力形式だった場合は変換コストも考慮して選ぶと良いかもしれません。
Adler-32 Checksum について
ほとんどの実装では Adler-32 によるチェックは行われないか、あるいはオプショナルであるため、今回の比較では行わないようにしています。
その他
比較結果について
Inflate は実装毎にバッファの管理方法が異なったりするため、展開するデータによって性能が上下することがあります。ここでの結果はあくまでも参考として利用した方が良いです。
zlib.js について
zlib.js では最新のコードは develop ブランチになっています。今回の比較では develop ブランチの実装を用いています。
ストリーム版 (inflate_stream.js) の結果も添付していますが、一度に全てのデータを流し込んでいるのであまり参考になりません。これは本来、断片的にデータが取得可能な場合に威力を発揮する実装です。
比較時の名前について
zlib-js と zlib.js は名前が似ているため zlib-js は iz-zlib と表記させていただきます。
すみません…。
比較結果
テキストデータ
The Three Musketeers
実行可能バイナリ
PINE
画像データ
HTML5 Logo (IDAT)
補足 (2012/08/15 - 23:22)
グラフの表示には jsperfview というものを使っているのですが、それで利用している Browserscope の API では最近のブラウザは表示されないようです。できるだけリンクをクリックして jsperf の方のグラフを見ることをおすすめします。
補足の補足 (2012/08/16 - 12:30)
jsperfview で利用している Browserscope の API パラメータを変更し、全てのブラウザの結果を表示するようにしました。