はじめに
先日、いつものように Twitter 監視業務に勤しんでいたところ、下記のような発言を見かけました。
asm.jsは対応してないブラウザでは読めないし遅いって説明をされることが多いけど、ams.jsはJavaScriptの中で高速実行可能なものだけを使って更に少し制約を加えて底上げをしてるものなので、多のブラウザであっても普通に人間が書いたコードよりも速いっすよ
— dynamis (でゅなみす) (@dynamitter) 2013, 11月 29
なるほど、機械によって生成された asm.js 対応のコードはどんなブラウザでも速いよという主張です。
自分は JavaScript で高速に動作するように注意して書いた zlib.js というのを作っていたので、zlib の展開処理でこの発言が本当か試してみることにしました。
zlib の展開処理というのは asm.js に向いていそうな処理ですし、ちょうど良いベンチマークになると思います。
zlib-asm vs zlib.js
比較には asm.js の zlib 実装として @ukyo さんの zlib-asm を採用しました。
ほかの zlib を Emscripten でビルドする系のプロジェクトはベンチマークコードも一緒に Emscripten でビルドしていて、ライブラリとしての単体利用が面倒くさそうだったからです。
その他、zlib-asm では Emscripten の生成したデフォルト状態のコードで遅い部分を最適化していて、もっとも良さそうな感じがしました。
(最初は asm.js が type error になって有効になっていなかったり最適化されていなかったのですが、連絡したらすぐに対応していただけました。ありがとうございます。)
zlib-asm 補足
zlib-asm は zlib のそのままのビルドではなく、zpipe という入出力を圧縮、展開するソフトウェアの Emscripten ビルドです。
zlib.js 補足
zlib.js は zlib の移植ではなく、JavaScript で(それなりに)高速に、ファイルサイズが小さくなるように開発しているライブラリです。
つまり、ここでの比較は zlib という仕様には従っているがまったく異なる実装の速度比較ということになります。
比較結果
比較用のページを用意しました。
手元の環境で実行した結果も貼っておきますが、自分でベンチマーク用のコードを見て実行してみるのが一番正確です。
Chrome 31
Filename | Size | Compressed |
zlib-asm (Emscripten) |
zlib.js Author: imaya |
---|---|---|---|---|
alice29.txt | 148,481 | 53,634 | 20.55 ms | 10.76 ms |
asyoulik.txt | 125,179 | 48,897 | 3.12 ms | 4.28 ms |
cp.html | 24,603 | 7,961 | 1.06 ms | 0.46 ms |
fields.c | 11,150 | 3,122 | 0.42 ms | 0.22 ms |
grammar.lsp | 3,721 | 1,222 | 0.35 ms | 0.11 ms |
kennedy.xls | 1,029,744 | 203,992 | 22.06 ms | 12.56 ms |
lcet10.txt | 419,235 | 143,106 | 9.72 ms | 10.67 ms |
plrabn12.txt | 471,162 | 193,730 | 15.06 ms | 10.04 ms |
ptt5 | 513,216 | 56,465 | 7.32 ms | 6.43 ms |
sum | 38,240 | 12,990 | 1.23 ms | 0.64 ms |
xargs.1 | 4,227 | 1,736 | 1.43 ms | 0.12 ms |
Firefox 25
Filename | Size | Compressed |
zlib-asm (Emscripten) |
zlib.js Author: imaya |
---|---|---|---|---|
alice29.txt | 148,481 | 53,634 | 2.58 ms | 6.61 ms |
asyoulik.txt | 125,179 | 48,897 | 1.72 ms | 4.69 ms |
cp.html | 24,603 | 7,961 | 1.68 ms | 0.72 ms |
fields.c | 11,150 | 3,122 | 0.55 ms | 0.27 ms |
grammar.lsp | 3,721 | 1,222 | 0.42 ms | 0.15 ms |
kennedy.xls | 1,029,744 | 203,992 | 7.01 ms | 16.51 ms |
lcet10.txt | 419,235 | 143,106 | 5.21 ms | 7.7 ms |
plrabn12.txt | 471,162 | 193,730 | 5.42 ms | 10.87 ms |
ptt5 | 513,216 | 56,465 | 3.05 ms | 5.2 ms |
sum | 38,240 | 12,990 | 0.86 ms | 0.83 ms |
xargs.1 | 4,227 | 1,736 | 0.46 ms | 0.41 ms |
Safari 7.0
Filename | Size | Compressed |
zlib-asm (Emscripten) |
zlib.js Author: imaya |
---|---|---|---|---|
alice29.txt | 148,481 | 53,634 | 16 ms | 4 ms |
asyoulik.txt | 125,179 | 48,897 | 4 ms | 4 ms |
cp.html | 24,603 | 7,961 | 1 ms | 1 ms |
fields.c | 11,150 | 3,122 | 1 ms | 1 ms |
grammar.lsp | 3,721 | 1,222 | 1 ms | 1 ms |
kennedy.xls | 1,029,744 | 203,992 | 24 ms | 17 ms |
lcet10.txt | 419,235 | 143,106 | 13 ms | 9 ms |
plrabn12.txt | 471,162 | 193,730 | 16 ms | 11 ms |
ptt5 | 513,216 | 56,465 | 6 ms | 5 ms |
sum | 38,240 | 12,990 | 2 ms | 1 ms |
xargs.1 | 4,227 | 1,736 | 0 ms | 1 ms |
傾向
asm.js が有効になっていないブラウザ(Chrome, Safariなど)では zlib.js が有利な結果になり、asm.js が有効になっているブラウザ(Firefox)では zlib-asm が有利な結果となりました。
まとめ
人間が書いた JavaScript でも機械の生成した asm.js 用のコードより速くなることもある。
あるいは、自分は人間ではなかった。
今回は人間で書いたコードのほうがasm.js非対応な環境では速くなることがありましたが、Emscriptenが出力するコードにはまだ非効率な部分が残っているため、これからもこの状況が続くとは限りません。
今後も見守っていこうと思います。
http://jsperf.com/fib-asm-js
このテストではChrome32から逆転しています
asm.jsが人が書いたコードより速いというのは
Emscriptenが人がJSで試行錯誤したコードより効率がいいコードをはけるということではありません
あくまで|0を付ける書き方の方が最適化されるよということです
それとasm.jsにもクセがあります
AOTとJITの性質もあって重さやコードによっては奮わないケースも当然有ります
http://jsperf.com/fib-asm-js/8
それからasm.jsとemscriptenでもっとも大事なのは将来性です