WebAssemblyで、JITコンパイラに迫る高速なJavaScriptエンジンを実装へ。Bytecode Allianceが技術解説。JavaScript以外の言語でも

2021年6月7日

Bytecode Alliance」は、WebAssemblyをWebブラウザだけでなく、デスクトップPCやサーバ、IoTデバイスなどあらゆる環境で、セキュアに実行することを目指している団体です。

Fastly、Mozilla、Arm、Google、マイクロソフト、インテルをはじめとする企業や団体が名前を連ねています。

参考:WebAssemblyをあらゆるプラットフォームでセキュアに実行できるようにする「Bytecode Alliance」発足。インテル、Mozilla、Red Hatなど

同団体は「WASI」と呼ばれる、どのOSやホストシステムでWebAssemblyモジュールが実行されたとしても、安全かつ透過的に共通のAPIでOSやホストシステムの機能を呼び出すための仕様などを策定中です。

例えば、この仕様を用いることでさまざまなプログラミング言語のポータブルなランタイムをWebAssemblyで実装できます

ただしWebAssemblyで実装できるのはインタプリタとしてのランタイムであり、ネイティブに実装されたJITコンパイラのような、ネイティブコードを動的に生成して実行するといったことは、言語の仕様上できません。

では、WebAssemblyによるランタイムは、JITコンパイラを採用したランタイムよりもつねに遅い実行速度しか期待できないのかと言うと、そうではないと、Bytecode Allianceのブログに投稿された記事「Making JavaScript run fast on WebAssembly」で解説されています。

fig

もしもWebAssemblyでJITコンパイラに迫る実行速度のJavaScriptエンジンが実装できれば、瞬時に起動するサーバレスコンピューティングのJavaScriptエンジンや、JITコンパイラが許されていないiOS上での高速なJavaScript実行が可能になります。

どのような技術を用いるとWebAssemblyによるJavaScriptエンジンがJITコンパイラに迫る性能を実現できるのでしょうか。Bytecode Allianceの記事「Making JavaScript run fast on WebAssembly」(以下、記事)を引用しつつ、ポイントを見ていこうと思います。

下記は、その記事の著者であるLin Clark氏のツイートです。

事前初期化ツールで初期化が13倍も高速に

記事では、JavaScriptエンジンの実行性能に大きくかかわるのは2つの要素「Initialization phaze」(起動時)と、「Runtime phase」(実行時)のスループットだと説明しています。

まず起動時の高速化には、事前初期化ツール(Pre-initializer)の「Wizer」を用いて、ビルド時にJavaScriptエンジンによるJavaScriptコードの初期化処理を実施。その内容は以下の様に説明されています。

At this point, the JS engine has parsed all of the JS and turned it into bytecode, which the JS engine module stores in the linear memory. The engine also does a lot of memory allocation and initialization in this phase.

この時点で、JavaScriptエンジンはすべてのJavaScriptコードを解析し、バイトコードに変換。JavaScriptエンジンモジュールはこれをリニアメモリに格納します。この段階ではまた、JavaScriptエンジンは多くのメモリの割り当てと初期化を行います。

この初期化済みのバイトコードをJavaScriptエンジンに持たせることで、初期化を高速化するとの説明ですが、近い将来、WebAssemblyのモジュールリンクが実現すれば、この初期化済みのバイトコードはJavaScriptエンジンと分離できるようになると。

Currently, we attach this data section to the same module as the JS engine. But in the future, once module linking is in place, we’ll be able to ship the data section as a separate module, allowing the JS engine module to be reused by many different JS applications.

現在のところ、このデータセクションはJavaScriptエンジンと同じモジュールにアタッチされています。しかし将来的にモジュールのリンクが実現すれば、データセクションを別のモジュールとして用意できるようになり、JavaScriotエンジンモジュールは、さまざまなJavaScriptアプリケーションで再利用できるようになるでしょう。

こうした処理によって初期化は圧倒的に高速化されると説明されています。

fig

2KB程度のインラインキャッシングで95%のコードをカバー

続いて、コードの実行時における速度について。

記事では、JITコンパイラによる主要な高速化テクニックとしてインラインキャッシングが挙げられています。

One optimization technique that JITs use is inline caching. With inline caching, the JIT creates a linked list of stubs containing fast machine code paths for all the ways a bit of JS bytecode has been run in the past.

JITコンパイラが使用する最適化技術の一つにインラインキャッシングがあります。インラインキャッシングでは、それまでに実行されたJavaScriptバイトコードすべてについて、JITコンパイラが高速な機械語のパスを含むスタブのリンクリストを作成します。

そして記事によると、このインラインキャッシングのパターンの95%程度が、あらかじめ用意した一般化された2キロバイト程度のインラインキャッシングでカバーできるとのこと。

We discovered that with just a few kilobytes of IC stubs, we can cover the vast majority of all JS code. For example, with 2 KB of IC stubs, we can cover 95% of JS in the Google Octane benchmark. And from preliminary tests, this percentage seems to hold for general web browsing as well.

私たちは、わずか数キロバイトのインラインキャッシュのスタブによって、あらゆるJavaScriptコードの大部分をカバーできることを発見したのです。例えば、Google Octaneベンチマークで用いられているJavaScriptコードの95%を、2KBのインラインキャッシュスタブでカバーすることができました。また、おおまかにテストした範囲でも、一般的なWebブラウジングにおいて同様の割合でした。

こうした高速化テクニックを用いることで、WebAssemblyによるJavaScriptエンジンの実装は初期のJITコンパイラによるJavaSriptエンジンに迫る性能を獲得できつとのこと。

さらにJITコンパイラが行っているようなコードのプロファイリングを導入できれば、現在のJITコンパイラ並みの性能を、より高速な起動時間とともに得られるとしています。

If we can figure out a way to put good tools in place for profiling, though, then there’s a chance we could actually make the JS run almost as fast as today’s JITs (and without the warm-up time!)

もしもプロファイリングのための優れたツールを導入する方法を見つけ出すことができれば、現在のJITコンパイラとほぼ同等の速度でJavaScriptを動作させることができる可能性があります(しかもウォームアップの時間が不要に!)。

MozillaのSpiderMonkeyで実装中

Bytecode Allianceでは、この実装をWebAssemblyランタイムの「Wasmtime」とMozillaのJavaScriptエンジンである「SpiderMonkey」、そして事前初期化ツールの「Wizer」を組み合わせて進めているとのこと。

そして同様の高速化テクニックがJavaScript以外の動的型付け言語でも利用できるだろうと、次のように呼びかけています。

If you’re part of a language community for a language like Python, Ruby, Lua, or others, you can build a version of this for your language, too.

あわせて読みたい

JavaScript WebAssembly Web技術




タグクラウド

クラウド
AWS / Azure / Google Cloud
クラウドネイティブ / サーバレス
クラウドのシェア / クラウドの障害

コンテナ型仮想化

プログラミング言語
JavaScript / Java / .NET
WebAssembly / Web標準
開発ツール / テスト・品質

アジャイル開発 / スクラム / DevOps

データベース / 機械学習・AI
RDB / NoSQL

ネットワーク / セキュリティ
HTTP / QUIC

OS / Windows / Linux / 仮想化
サーバ / ストレージ / ハードウェア

ITエンジニアの給与・年収 / 働き方

殿堂入り / おもしろ / 編集後記

全てのタグを見る

Blogger in Chief

photo of jniino

Junichi Niino(jniino)
IT系の雑誌編集者、オンラインメディア発行人を経て独立。2009年にPublickeyを開始しました。
詳しいプロフィール

Publickeyの新着情報をチェックしませんか?
Twitterで : @Publickey
Facebookで : Publickeyのページ
RSSリーダーで : Feed

最新記事10本