WebAssembly は今どこにあり、次に何があるのか

[この記事は”Where is WebAssembly now and what’s next?“の翻訳です]この記事は WebAssembly と何が速くしたのかのシリーズの6部です。もしまだ前の記事を読んでいない場合、最初から読むことをお勧めします。

2月28日、4つのメジャーなブラウザが WebAssembly の必要最低限の機能のみを持つ製品 (MVP) が完了したという コンセンサスを発表しました

これにより、ブラウザが出荷できる安定したコアが提供されます。このコアには、コミュニティグループが計画している機能のすべてが含まれているわけではありませんが、WebAssembly を高速かつ使いやすくするために十分な機能を備えています。

これにより、開発者は WebAssembly コードの提供を開始できます。以前のバージョンのブラウザでは、開発者は asm.js バージョンのコードを提供できます。asm.js は JavaScript のサブセットであるため、どの JS エンジンでも実行できます。Emscripten を使用すると、同じアプリケーションを WebAssembly と asm.js の両方にコンパイルできます。

初回リリースであっても WebAssmbly は高速に動くでしょう。しかし修正と新規機能を導入により将来的にさらに高速になるでしょう。

ブラウザー上の WebAssembly のパフォーマンス向上

ブラウザーエンジンが WebAssembly のサポートを向上させるとスピードが向上します。ブラウザベンダーはこれらの問題を個々に取り組んでいます。

JS と WebAssembly 間の関数呼び出しの高速化

現在 JS からの WebAssembly 関数呼び出しは求められるスピードに達していません。その理由は「トランポリン」と呼ばれることが原因です。JIT は WebAssembly をどのように扱えばよいのか知らないため、WebAssemblyを何かにルーティングする必要があります。これは最適化された WebAssembly コードを実行するためのセットアップ時のエンジン自体のコードが遅い箇所です。

Person jumping from JS on to a trampoline setup function to get to WebAssembly

これは JIT が直接処理する方法を知っていた場合よりも、最大100倍遅くなることがあります。

単一の大きなタスクを WebAssembly モジュールに渡している場合は、このオーバーヘッドに気付かないでしょう。しかし WebAssembly と JS の間で多くのやりとりがある場合 (小規模な作業と同じように)、このオーバーヘッドが目立ちます。

より速いロード時間

JIT はより速いロード時間とより速い実行時間の間のトレードオフを管理する必要があります。コンパイルや最適化に時間を費やすと実行速度が向上しますが、起動が遅くなります。

先進的なコンパイル (コードが実行されるとジャンクが発生しないようにする) と、コードのほとんどの部分がそれに見合った最適化を行うために十分な時間実行されないという基本的な事実とのバランスを取るために、多くの進行中の作業があります。

WebAssembly はどの型が使用されるかを特定する必要が無いため、エンジンは実行時に型をモニターする必要がありません。これは実行時の平行コンパイルといった例のような様々なオプションをもたらします。

さらに JavaScript API への最近の追加では WebAssembly のストリーミング・コンパイルが可能です。これは WebAssembly のデータをダウンロード中にエンジンがコンパイルを開始できることを意味します。

Firefox では二つのコンパイラーを使用するシステムになっています。一つ目のコンパイラは事前に実行し、コードを最適化を行います。コードの実行中は別のコンパイラがバックグラウンドで完全な最適化を行います。完全に最適化されたバージョンのコードへ準備が整うと切り替わります。

MVP リリース以降の機能導入

WebAssembly の目標の 1 つは、すべての機能を設計するのではなく、小さなチャンクで指定し、途中でテストを行うことです。

期待されている機能はたくさんあるが、100% の考え方はまだ存在しないことを意味しています。これらはブラウザベンダが参加している使用策定プロセスを経る必要があります。

これらの機能は将来の機能と呼ばれています。少し紹介します。

DOM を直接扱う

現在 DOM を扱う手段はありません。これは WebAssembly から element.innerHTML のようにノードを更新できないこと意味します。

代わりに、値を設定するために JS を経由する必要があります。これは値を JavaScript 呼び出し側に渡すことを意味します。一方、WebAssembly 内から JavaScript 関数を呼び出すことは、JavaScript と WebAssembly の両方の関数を WebAssembly モジュールをインポートして使用できることを意味します。

Person reaching around from WebAssembly through JS to get to the DOM

いずれにしても、JavaScript を使用することは直接アクセスよりも遅くなる可能性があります。WebAssembly の一部のアプリケーションはこれが解決されるまでが続くかもしれません。

共有メモリーの同時実行性

コードを高速化する方法の 1 つは、コードの異なる部分を同時に並列で実行できるようにすることです。しかし、スレッド間の通信のオーバーヘッドは、タスクを分けずに実行するよりも多くの時間を要する可能性があるため、時には逆効果になる場合があります。

しかしスレッド間のシェアードメモリを使用すればこのオーバーヘッドを削減できます。これを実施するため WebAssembly は JavaScript の新しい SharedArrayBuffer を使用すべきです。これがブラウザに組み込まれると、ワーキンググループは WebAssembly の動作方法を指定することができます。

SIMD

WebAssembly に関する他の投稿を読んだり、話を聞いたりすると、SIMD のサポートについて聞かれることがあります。頭字語は、単一命令、複数のデータを表します。物事を並行して運用する別の方法です。

SIMD を使用すると、異なる数のベクトルのような大きなデータ構造を取り、同じ命令を異なるパーツに同時に適用することができます。このようにして、ゲームや VR に必要な複雑な計算を大幅に高速化できます。

これらは平均的な Web 開発者にとってさほど重要ではありません。しかしゲーム開発者のようなマルチメディアを扱う開発者にとって非常に重要です。

例外ハンドリング

C++ のような言語の多くのコードは例外を使用しています。しかし例外は WebAssembly の一部としてまだ定義されていません。

あなたのコードを Emscripten でコンパイルした場合、いくつかのコンパイラ最適化レベルの例外処理をエミュレートします。これは非常に遅いため、DISABLE_EXCEPTION_CATCHING フラグを OFF にできます。

WebAssembly で例外がネイティブに処理できるようになると、このエミュレーションは必要ありません。

開発者にとってより簡単にするその他の改善

いくつかの将来の機能はパフォーマンスは改善しませんが、WebAssembly を使用するにあたり開発者がより簡単に使用できるようになるでしょう。

  • ファーストクラスのソースレベル開発ツール. 現在ブラウザ上で WebAssembly をデバッグすることは、生のアセンブリーをデバッグするようなものです。しかし、ソースコードがアセンブリにどのように変換されるかに関して精通している開発者はほとんどいません。開発者がソースコードをデバッグできるように、ツールサポートを改善する方法を検討しています。
  • ガベージコレクション. 事前に型を定義できる場合は、コードを WebAssembly に変換する必要があります。したがって TypeScript のようなコードを使用するコードは、WebAssembly にコンパイル可能である必要があります。WebAssembly は JS エンジンに組み込まれているような既存のガベージコレクタとやりとりができないというのが現状です。この将来の機能のアイデアは、WebAssembly に低レベルの GC プリミティブタイプとオペレーションのセットを使用して、組み込み GC へのファーストクラスのアクセスを与えることです。
  • ES6 モジュールの統合. ブラウザは現在、script タグを使用して JavaScript モジュールを読み込むためのサポートを追加しています。 この機能を追加すると、url が WebAssembly モジュールを指している場合でも<script src=url type="module">のようなタグが機能します。

結論

WebAssembly は今日でも高速で、そしてブラウザの新しい機能や実装の改良により、さらに高速化するはずです。

Lin Clark に関して

Lin は Mozilla Developer Relations チームのエンジニアです。 彼女は JavaScript、WebAssembly、Rust、Servo を使っています。また、コードの漫画を描きます。

Lin Clark によるその他の記事はこちら…

2 件のコメント

  1. 5.5 :

    「平行コンパイル」→「並行コンパイル」,「使用策定プロセス」→「仕様策定プロセス」,「これが解決されるまでが続くかもしれません」→?,「頭字語は」→「この頭字語は」でしょうか。

  2. AnonymousCoward :

    この回には(既に指摘がある以外の)誤訳は見つかりませんでした。

    以上、誤訳を指摘しましたが、基本的に読んでいて気になった点を原文で調べただけなので、これがすべてではないでしょう。
    また、誤訳未満の読みづらい訳などは基本的に指摘していません。
    最後に、繰り返しになりますが、誤訳の量は(企業や著名コミュニティなどの水準で考えて)わりと少ない方であり、質の高い翻訳でした。