RSS Twitter Facebook

2013/05/27 (2013年05月 のアーカイブ)

asm.js は本当に速いのか?

現在 Firefox aurora に搭載されている asm.js についてとにかく「爆速」というような記事を良く見かけるのですが、asm.js を使ったFFTモジュールを書いてみたのだけどどうも思ったような性能が出ないなあ、という事で先日記事を書きました。

asm.jsでFFTしてみた、のだが。

その時の結果がこちら

時間
Firefox ASM,10000回4156
Firefox NoASM,10000回6009
Chrome 10000回4859
IE10 10000回12164

この結果から、確かにFirefoxとしてはasm.jsが有効になる事で速くはなっているのだけど、asm.js 非対応のChromeと大して変わらない(場合によっては負ける)、というのがわざわざ文法を変えてまで改善した結果としては物足りない、という所ですね。

なお、このテストは実用的なFFTモジュールを目指していてデータの入出力部に通常のJavascriptとのインターフェースのために非asm.jsの処理が多少残っていますので、純粋なベンチマークならばもう少しasm.jsでの改善具合は良くなると思います。


しかしながら、触ってみた実感と世の中の爆速という評判との乖離に釈然としないものを感じていたわけです。1つは比較対象が何であるかという点だと思います。これは数日前の記事。
Surprise! Mozilla can produce near-native performance on the Web
ここに出ている数値自体は割合納得できました。near-nativeという言い方ですが、通常のJavaScriptに対して2倍程度の性能って所でしょうか。ただ比較対象の他のブラウザとしては現時点明らかに勝てるであろうIEしか出ていません。

という事で、今回は竹内関数(Tarai Function)でのベンチマークをとってみます。Tarai Function は下のリストのような関数で、数値演算でもなくほとんどが関数呼び出しの速度に依存するのですが、これはFirefoxにとってはかなり有利な条件だと思います。


function tarai_n(x,y,z) {
	if(x <= y)
		return y;
	return tarai_n(tarai_n(x-1,y,z),tarai_n(y-1,z,x),tarai_n(z-1,x,y));
}

JavaScriptエンジンにはそれぞれ得意不得意があります。私が使っている限りでの一般的な使用においては、平均的にはFirefoxよりChromeの方がちょっと速いかなと思っているのですが、関数呼び出しについてはFirefoxが速いです。

使用したバージョンは:
Firefox は 23.0a2(2013-05-26)
Chrome は 28.0.1500.20
IEは10.0.9200.16576
です。


使用したベンチマークはこちら:Tarai function benchmark
  • RegularJS : 通常のJavaScript文法で書いたもの
  • ASM/NoASM int : asm.js文法でintに型付けして書いたもの (x|0 という奴)
  • ASM/NoASM double : asm.js文法でdoubleに型付けして書いたもの (+x という奴)
  • NoASM は "use asm"; を付けていないので asm.js が有効になっていません
時間
FirefoxRegularJS tarai(14,7,0)3131
ASM double tarai(14,7,0)6027
ASM int tarai(14,7,0)3312
NoASM double tarai(14,7,0)8312
NoASM int tarai(14,7,0)8333
ChromeRegularJS tarai(14,7,0)4745
NoASM double tarai(14,7,0)6101
NoASM int tarai(14,7,0)6004
IE10RegularJS tarai(14,7,0)7681
NoASM double tarai(14,7,0)8138
NoASM int tarai(14,7,0)9339

こんな感じになりました。まず、RegularJSで比べるとFirefox 3131、Chrome 4745。やっぱりFirefoxは関数呼び出しに強いです。そして、asm.js の文法に沿った書き方にしてみると、NoASM double Firefox 8312、Chrome 6101。あれ、逆転しちゃいました。+ 演算子とかに対するペナルティがFirefoxだと結構大きいですね。しかしここから、Firefoxは asm.js によるパフォーマンス改善があって ASM double で6027まで改善します。

つまり
Chrome 4745 => 6101 に対し、Firefoxは 3131 => 8312 => 6027
という推移。ほぼChromeに並びます。

そして更に、asm.jsでintに型付けすると
Chromeは 4745 => 6004、に対しFirefoxは 3131 => 8333 => 3312
という推移。asm.js対応ソースでChromeの倍くらいの速度が出ます。

とは言うものの、これではFirefox自身のRegularJSの数値と変わらんではないか...。asm.js文法によるペナルティを取り戻しただけという...。

文法に制約を設けて最適化するのだから競争するべき相手は、「他のブラウザ」と「本来の文法」という2つがありますよね。今このあたりがごっちゃになっているような気がします。対Chromeで考えるとFirefoxがもともと優位な傾向だった処理で優位。しかし本来のJavaScriptと比べるともともと優位だった処理ではあまり優位性が出ない、という板ばさみ的状況。

asm.jsが明らかに優位性を発揮できるのは C++をemscriptenで変換したコードだけって言う事なのかなあ。元がC++とかなら元々JavaScriptでゴリゴリにチューンしたコードと比較される事はないし元のネイティブに対して何倍という言い方になるものね。emscriptenが吐くコードを精査したわけではないけど無駄があってそのオーバーヘッドを解消する、みたいなストーリーは成立しやすそうです。メインターゲットは確かにそこだとは思うのだけどね。

とりあえずわかった事は asm.js の double/int 間の差は結構大きい。可能なかぎりintに型付けすべし、という事。

手書きasm.jsに爆速の道は残されているのか!? (続く...のか?)

Posted by g200kg : 2013/05/27 06:52:46