JägerMonkey による JavaScript パフォーマンス向上
2008 年 08月、Mozilla は TraceMonkey を導入しました。私たちが Firefox 3.5 に搭載したこの新しい JavaScript エンジンは、次世代の Web ブラウザと Web アプリケーションを構築する新時代のパフォーマンスを実現するものとして歓迎されました。私たちが新しいエンジンを公開して間もなく、Google は V8 を搭載する Chrome を公開しました。Apple もまた、Safari に独自のエンジンを導入し、Opera も最新のベータ版ブラウザに新しいエンジンを搭載しています。
これらの新エンジンが登場した結果、新しい種類のアプリケーションが登場するのを目の当たりにすることになります。Processing を Web で実現してみる人もいれば、リアルタイムオーディオ編集 や ゲーム など、様々なものが試されるようになりました。(他にも Canvas デモリスト で紹介したものもご覧ください)
このようなアプリケーションと JavaScript エンジンの関わりについて、私たちは Mozilla で 2 つのことが分かっています:
- ある種のコードスタイルでは、私たちの Tracing による手法では上手く高速化できないことがある。(例えば前述のファミコンエミュレータでは、私たちのエンジンでは上手く高速化されませんが、これは主に長大な switch 文に起因しています)
- 「Trace 上にいる」(後述します) 限りにおいては、TraceMonkey は他のすべてのエンジンに勝っている。
Mozilla のエンジンは他のエンジンとは根本的に異なっています。他のエンジンは全て、いわゆる「メソッドベース JIT」を採用しており、読み込んだ JS コードを全て機械語にコンパイルし、実行しています。一方で Firefox は「Tracing JIT」を採用しています。Firefox では読み込んだ JS コードを全てインタープリタで実行しながら記録します。ホットパスを検出すると、それを機械語に変換して実行します。(Tracing について詳しくは昨年 hacks.mozilla.org に投稿された記事をご覧ください)
訳注: Tracing についての日本語での解説は訳者が公開している解説スライドをご覧く ださい
Tracing JIT の問題は、ある条件にあてはまるとインタープリタと機械語を相互に切り替えながら実行する必要があることです。機械語からインタープリタに戻らなければならない場合のことを「Trace が中断された」と表現しています。もちろん、インタープリタはネイティブな機械語よりも遙かに遅くなりますが、それが誰もが想定していたよりも多く発生することが分かりました。
そこで私たちは、第2世代のエンジンでは両手法のいいとこ取りをすることにしました:
- WebKit JS エンジンの一部分を流用して新しいメソッド JIT エンジンを実装し、それを用いて JavaScript コードを実行します。これにより JS 実行速度のベースラインは他のエンジンと同程度に引き上げられます。ここで最も重要なことは、コードに依らずおしなべて高速化されることです。言い換えれば、機械語との切り替えてインタープリタでの低速実行する必要がなくなるということです。
- 機械語を内部のループで更に高速なコードに変換するために Tracing エンジンを組み合わせます。つまり、コードに依らず高速化できるメソッドベース JIT に加えて、Tracing エンジンの強みも活かせるようにします。
この開発はまだ非常に初期の段階であり、デモをお見せできる段階にはありませんが、私たちが何をしようとしているのか知ってもらうのも良いと思ってこの記事を書きました。
より詳しく知りたい方は David Mandelin やDavid Anderson のブログや 新エンジンのプロジェクトページ をご覧ください。