数か月前に、Asm.jsのリリースを発表しました。 Asm.jsのサポートは、2014年12月のリリース以来、Microsoft Edgeに対して最もリクエストが多かった10 件のユーザー音声要求の 1つです。それ以来、順調に進歩しています。Windows10 Insider Previewでは、ビルド10074以降、Asm ChakraおよびMicrosoft Edgeの.js。
Asm.jsとは何ですか?
Asm.jsは、コンパイラの低レベルで効率的な言語として使用できるJavaScriptの厳密なサブセットです。 asm.jsのサブセットとして、CやC ++などの安全でないメモリアクセスを持つ言語用の限定された仮想マシンについて説明します。 静的チェックと動的チェックの組み合わせにより、JavaScriptエンジンは、保険なしの特殊なコンパイルや、正しいasm.jsコードのAOT-of-Timeコンパイルなどの手法を使用できます。
このような手法は、JavaScriptが「予測可能な」パフォーマンスと「ネイティブに近い」パフォーマンスで実行するのに役立ちます。これらはどちらも、JavaScriptなどの動的言語の通常のコンパイラ最適化のフレームワーク内で達成するのは容易ではありません
asm.jsコードを手動で記述することの複雑さを考えると、今日asm.jsは主にEmscriptenなどのツールを使用してC / C ++コードをトランスコンパイルすることによって行われます。 結果は、WebGLやWeb AudioなどのテクノロジーとともにWebプラットフォームの一部として使用されます。 UnityやUnrealなどのゲームエンジンは、asm.jsと他の関連技術の組み合わせを使用して、プラグインを使用せずにWeb上のゲームの早期または実験的なサポートを導入し始めています。
Microsoft EdgeでAsm.jsを試すにはどうすればよいですか?
Microsoft EdgeでAsm.jsサポートを有効にするには、以下に示すように、Microsoft Edgeのabout:flagsページに移動し、「asm.jsを有効にする」フラグを有効にします。
Chakraコード実行スレッドへのAsm.jsの埋め込み
Asm.jsをChakraに追加するために、緑色で強調表示されたコンポーネントは、Windows 10のJavaScriptパフォーマンスの改善に関する記事で説明されている基本的なコード実行モデルと比較して追加または変更されています 。
主な変更:
- ASM.jsバリデータ。Chakraが asm.jsコードを検出し、asm.js仕様に一致することを確認できます。
- 最適化されたタイプ固有のコードの生成 。 asm.jsがネイティブ型(int、double、float、またはSIMD値)のみをサポートする場合、Chakraは型情報を使用して、asm.jsのコードに基づいて型固有のコードを生成します。
- タイプ情報を使用して数値のパッケージ化とアンパックを除外し、解釈用のデータプロファイルを生成する必要性を排除することにより 、Chakraインタープリターによるタイプ固有コードの高速実行 。 非asm.js JavaScriptコードの場合、ChakraインタープリターはJITコンパイラー用のデータプロファイルを作成および維持して、高度に最適化されたJITコード生成を提供します。 正しいasm.jsコードに基づいて作成された型固有のバイトコードには、JITコンパイラーが最適化されたマシンコードを作成するために必要なすべての情報が既に含まれています。 型に特化したインタープリターは、データプロファイルを備えたインタープリターよりも4〜5倍高速です。
- Chakra JITコンパイラによる高速コンパイル 。 Asm.jsコードは通常、 LLVMコンパイラとEmscriptenツールを使用して生成されます 。 Chakra JITコンパイラーは、LLVMコンパイラーによって生成されたasm.jsコードに既に存在する最適化を考慮に入れます。 たとえば、当社のJITコンパイラーは埋め込みコードを渡しません。LLMVコンパイラーによって既に行われた埋め込みに焦点を当てています。 このようなJIT最適化のコード分析の例外は、コード生成時のCPUサイクルとバッテリー使用量の節約に役立つだけでなく、JITコンパイラーの速度を大幅に向上させます。
- コンパイルされたasm.jsコードの保険を削除することにより、 予測可能なパフォーマンス 。 JavaScriptの動的な性質を考慮すると、最新のJavaScriptエンジンはすべて、保険と呼ばれる最適化されていないコードの実行への何らかの移行をサポートします(この場合の「救済」は保険として翻訳されます)。 エンジンが、JITコンパイラーによって行われた仮定がコンパイルされたコードに当てはまらないことを認識すると機能します。 保険は全体的なパフォーマンスに影響するだけでなく、リードタイムを予測不能にします。 正しいasm.jsコードの安全な型制限を利用して、Chakra JITコンパイラーによって生成されたコードは保険を必要としないことが保証されています。
Asm.js用のJITコンパイラーの最適化
上記のコード実行プロセスの変更に加えて、Chakra JITコンパイラーはasm.jsによって課せられた制限も利用します。 これらの機能強化により、Chakra JITコンパイラーは、ネイティブ言語に近いパフォーマンスで実行されるコードを生成できます。これは、すべての動的言語JITコンパイラーの目標です。 このような2つの最適化を詳しく見てみましょう。
アシスタントコールと保険を除外する
ヘルパーおよび保険コードは、コンパイルされた動的言語コードの強力なライフラインとして機能します。 コードのコンパイル中にJITコンパイラーによって行われた仮定のいずれかが不正確になった場合、コードを正しく実行するための安全なメカニズムが必要です。
ヘルパーを使用して、操作中の予期しない状況を処理できます。その後、制御をJITコードに戻すことができます。 保険会社は、予測できない状況の発生からJITコードを回復できず、現在の機能の残りを実行するために制御をインタープリターに戻す必要がある状況を処理します。
たとえば、変数が整数であると思われ、コンパイラがこの仮定でコードを生成した場合、実数の出現は正確さに影響を与えません。 そのような場合、アシスタントまたは保険コードを使用して、パフォーマンスが低下しても実行を継続します。 asm.jsコードの場合、Chakraは追加のヘルパーコードまたは保険コードを生成しません。
これが必要ない理由を理解するために、asm.jsモジュール内の2乗関数の例を見てみましょう。これは、概念を説明するために単純化されています。
function PhysicsEngine(global, foreign, heap) { "use asm"; … // Function Declaration function square(x) { x = +x; return +(x*x); } … }
上記のコード例のsquare関数は、2つのx64-machine命令をasm.jsコードに変換しますが、この関数に対して生成されたプロローグとエピローグは除きます。
xmm1 = MOVAPS xmm0 // double xmm0 = MULSD xmm0, xmm1 //
比較のために、asm.jsをオフにしてsquare関数用に生成されたコンパイル済みコードには、約10の機械語命令が含まれています。 含む:
- パラメーターがdoubleとしてマークされていることを確認します。そうでない場合は、ヘルパーに移動して、任意の型からdoubleに変換します
- マークされたdoubleから実際の値を抽出する
- 値の乗算
- 結果をマークされたdoubleに戻す
Chakra JITコンパイラーは、asm.jsの効率的なコードを生成することができ、変数の型情報を利用します。これは、プログラムの存続期間にわたって変化しません。 Asm.jsバリデーターとリンカーもこれを考慮します。 asm.jsのすべての内部変数はネイティブ型(int、double、float、またはSIMD値)を持っているため、内部関数は関数間で渡すためにJavaScript変数にパックせずに冷静にネイティブ型を使用します。 コンパイラーの用語では、これは直接呼び出しと呼ばれ、asm.jsコード内のデータを操作する場合のパッケージ化または変換の例外と呼ばれます。 さらに、JavaScriptへの、またはJavaScriptからの外部呼び出しの場合、すべての着信変数はネイティブ型に変換され、発信ネイティブ型はパッケージ化時に変数に変換されます。
型付き配列にアクセスするときの境界チェック例外
前回の投稿で、Chakra JITコンパイラーが自動的に型指定された配列の最適化を実装する方法について説明しましたが、 配列の外側で境界チェックを行い、ループ内の配列の操作のパフォーマンスを最大40%向上させました。 asm.jsの型制限を考慮すると、Chakra JITコンパイラーは、コード内の場所(ループまたは関数の内側または外側)または型付き配列の型に関係なく、コンパイルされたすべてのasm.jsコードの型付き配列へのアクセスの境界チェックを完全に除外します。 また、型付き配列に対する永続的および非永続的なインデックス付きクエリの境界チェックを排除します。 これらの最適化により、asm.jsコードで型付き配列を操作するときにネイティブに近いパフォーマンスを実現できます。
以下は、asm.jsの対応するコード用にChakraコンパイラーによって生成された定数シフトと1つのx64マシン命令を使用して、型付き配列に格納する単純化された例です。
int8ArrayView[4] = 25; //JavaScript- [Address] = MOV 25 //
asm.jsコードをコンパイルするとき、Chakra JITコンパイラーは、asm.jsコードのアセンブリ中(asm.jsモジュールの最初の呼び出し)に直接int8ArrayView [4]に対応する最終アドレスを事前計算できるため、保存に対応する1つの命令を生成できます。型付き配列。 比較のために、非asm.js JavaScriptコードから同じ操作用に生成されたコンパイル済みコードは、約10〜15の機械語命令につながります。これは非常に重要です。 操作には次の手順が含まれます。
- 型付き配列をクロージャー内の変数からロードする(asm.jsでは、型付き配列は既にクロージャーによってキャプチャされています)
- クロージャーからの変数が実際に型付き配列であることを確認します;そうでない場合、安全コードが呼び出されます
- インデックスが型付き配列の長さ内にあることを確認してください。 条件が満たされない場合、アシスタントまたは保険のコードへの移行があります
- 配列バッファーに値を保存する
上記のチェックは、asm.jsモジュール内で変更できるものに厳しい制限があるため、asm.jsコードから削除されます。 たとえば、asm.jsモジュールの型付き配列を指す変数は変更されません。 変更された場合、これはasm.jsの正しいコードではなく、コード検証の段階でキャッチされます。 このような場合、コードは他のJavaScript関数と同様に処理されます。
Asm.jsによるスクリプトの改善と生産性の向上
Windows 10プレビューの新しいビルドで試すことができる最初の結果から、ChakraとMicrosoft Edgeでのasm.jsサポートのパフォーマンスの恩恵を受けるクールなスクリプトを見ました。 自分でプレイしたい場合は、 Angry Bots 、 Survival Shooter 、 Tappy Chickenなどのゲームを開始するか、 ここで楽しいasm.jsデモを試してください。
パフォーマンスの改善という点では、絶えず進化しているいくつかのasm.jsスピードメーターがあります。 asm.js ChakraとMicrosoft Edgeは 、予備サポートが既にあるため、 Unity Benchmarkで300%以上 、Google OctaneおよびApple Jet Streamテストスイートで使用されるzlibなどの個々のテストで約200%高速に動作します。
64ビットブラウザーのUnityベンチマークスコア(クリックして拡大)
(システム情報:Intel Core(TM)i7 CPU 860 @ 2.80GHz(4コア)、64ビットWindows 10 Previewを実行する12GB RAM)
(スコアはIE11 = 1.0になるようにスケーリングされており、単一のチャートに収まります)
次は?
これは、asm.jsをMicrosoft Edgeの背後にあるWebプラットフォームに統合するための最初のステップです。 結果には満足していますが、まだすべてが終わっているわけではありません。 Chakraのコード実行チェーンを微調整してAsm.jsをサポートしています。現在のアーキテクチャアプローチが実際のasm.jsの使用シナリオで適切に機能することを確認するためにデータを収集し、パフォーマンス、機能、ツールサポートなどを分析して改善しようとしています。 n。 このオプションをデフォルトで有効にする前。
有効にすると、asm.jsはMicrosoft Edgeで機能するだけでなく、Microsoft Edgeに付属のEdgeHTMLレンダリングエンジンを使用するため、HTML / CSS / JSで記述されたWindowsアプリケーションおよびWebViewでも使用可能になります。 Windows 10。
また、asm.jsのサポートの実装の最初から緊密に協力してきたMozillaの同僚、およびChakraとMicrosoft Edgeでのasm.jsの実装のサポートと協力についてUnityに感謝します。 そして、貴重なフィードバックを残してくれたWindows 10およびMicrosoft Edgeのすべての開発者とユーザーに感謝します。 良い仕事を続けてください! Twitterの@MSEdgeDevまたはConnectを介してメールでお問い合わせください。