モバイルデバイス向け HTML5 および JavaScript エンジン JIT の最適化

同カテゴリーの次の記事

Android* 開発者向けラーニングシリーズ 1: インテル® プロセッサーで動作する Android* の紹介

この記事は、インテル® デベロッパー・ゾーン(IDZ)サイトに掲載されている「Graphics Acceleration for HTML5 and Java Script Engine JIT Optimization for Mobile Devices」の日本語参考訳です。


HTML5[1] は、Web の未来であると見なされ、過去のネイティブ・アプリケーションでのみ見られたより優れたユーザー体験を提供することが期待されています。これは、これまで以上に豊かなコンテンツを扱うはるかに重いWebアプリケーションを維持するため、パフォーマンスへの要求が大幅に高まります。その結果、Webランタイムの最適化は、特にモバイル機器は PC よりも非力であるためプラットフォームの成功を達成するにはきわめて重要となります。

この記事では、最初にHTML5 によって生じるパフォーマンス面の課題に触れます。レンダリング・エンジンと JavaScript エンジンは、Web ランタイムの 2 つの重要な基本構成要素であるため、私たちのグラフィック・アクセラレーションのソリューションとこれら 2 つの要素それぞれに劇的にパフォーマンスを改善するインテル® Atom™ プラットフォームに適用されたジャスト・イン・タイム(JIT)の最適化について説明します。この記事では、一般的な HTML5 と JavaScript のベンチマークによって私たちが提唱するソリューションの影響を評価し、同様に将来のビジョンも示しています。

はじめに

HTML5 はオープンで魅力的な Web テクノロジーであり、Web の未来であると考えられています。それにより、より多くのクライアント・アプリケーションが HTML5 によって作成され、クラウドに接続され Web 全体に配備されます。ガートナー[3]によると、モバイル・アプリケーションの半数が 2015 年までに Web アプリケーションとなり、HTML5 がその重要な原動力の 1 つであると推測されています。最近の典型的な例では、HTML5 のバージョンに対応した Angry Birds[4] ゲームが上げられ、既存のネイティブ・アプリケーションと同じユーザー体験を提供しています。しかし、HTML5の普及にはストレスのないユーザー体験を維持するため、クライアントデバイスにおいてパフォーマンスの大幅な向上が求められます。

今日の Web アプリケーションは、ページをサーフしてナビゲートする従来の Web よりもはるかに多い計算を行います。それらは通常処理が重く、より複雑なロジックを持っています。Gmail クライアントの JavaScript のソースは、2010 年に 443,000 行に達し、6 年前の 50 倍にまで増えています。[5] さらに、カメラとセンサーが搭載されたモバイルデバイスの普及により、HTML5 Web アプリケーションは、イメージやHD ビデオクリップなど劇的にリッチなコンテンツを生産そして消費します。最後に、魅力あるユーザー体験では、タッチやジェスチャーなどユーザーのアクションに対して即座な応答が求められます。これは、Web ランタイムが、タイムリーにそのような優先度の高いインタラクティブなタスクを処理することが可能であることを意味します。

また、Web アプリケーションには、 C/C++、Java、そして .NET といった言語で開発されるネイティブや伝統的なマネージド・バイナリーと比べ、多くのパフォーマンスの課題があります。HTML5 は、クロスプラットフォームへの実装を約束しますが、これは、JavaScript、HTML、そして CSS の抽象化レイヤーを介して行われます。このような抽象化は、ネイティブ・ソリューションよりもオーバーヘッドが大きくなります。例えば、JavaScript のパフォーマンスは、過去 10 年間で 100 倍以上向上しているにもかかわらず[6]、多くの場合 C/C++ と比べると少なくとも 1 桁低速です。一方、HTML5 はまだ新しい技術です。したがって、すでに 10 年以上にわたって十分に最適化されてきた Java や .NET ランタイムとは異なり、HTML5 のソフトウェア・スタックはまだ早熟であり機能とパフォーマンスの両面で改善の余地があります。

複雑な Web ランタイム・アプリケーションでは、レンダリング・エンジンや JavaScript エンジンが重要な役割を果たしており、HTML5 アプリケーションのほとんどはそのパフォーマンスに左右されます。レンダリング・エンジンはコンテンツを描画し、操作システムがディスプレイ上に表示できるようにそれらを準備する責任があります。JavaScript エンジンは、JavaScript によって構成されるアプリケーションのロジックを実行します。私たちの分析では、Android*[7] 携帯電話上で両者の合計は、典型的な HTML5 ゲームや高密表示のナビゲーションにおいて CPU 実行サイクルの 60% 以上を占めていることが明らかになっています。

したがって、既存の最適化の労力の多くは、これら 2 つのコンポーネントを対象としています。例えば、Chrome[8] などの比較的新しいデスクトップ・ブラウザーは、レンダリング・エンジンの効率を向上させるため、特に HTML5 の canvas 2D ではグラフィック・アクセラレーションを使用します。また、JIT 技術と他の高度なコンパイラー技術が、JavaScript エンジンに適用されています。V8[10] JavaScript エンジンのCrankshaft[9] は、Google の計測によると v8bench[11] のスコアを 50% 以上向上させています。

それにもかかわらず、Android や Linux ベースの電話やタブレットなどのモバイルデバイスでは、処理速度は非常に遅くなります。Android ブラウザーは、最新の Android 4.0 でも HTML5の Canvas 2D の描画にまだ CPU のみを利用しています。WebKit[12] は、最も人気のある Web エンジンのひとつです。DFG (Data Flow Graph) JIT と呼ばれるアドバンスド JIT 技術は、2011 年にJSC (JavaScriptCore) に導入されたホットスポットを最適化する技術であり、WebKit に含まれるデフォルト JavaScript エンジンですが、x64 アーキテクチャーのみをサポートしIA32 アーキテクチャーでは動作しません。

この記事では、モバイルデバイスにおいてこのような状況を変えることを目標としています。記事の残りの構成は次の通りです: ”Android 4.0 における HTML5 Canvas 2D のグラフィック・アクセラレーション”では、インテル Atom ベースのプラットフォームにおける HTML5 Canvas 2D のハードウェア・アクセラレーションに関してインテルのソリューションを詳しく説明します。 “ IA32 上の DFG JIT” では、32 ビットのインテル・アーキテクチャー・プラットフォームにおける DFG JIT の有効化の詳細を紹介します。”まとめと今後の展開”では、両分野での今後のインテルの開発作業の見解を示します。

Android 4.0 におけるHTML5 Canvas 2Dのグラフィック・アクセラレーション

HTML5 Canvas 2D[13] は、最も重要な成熟した機能のひとつであり、広く現代のモバイルデバイスでサポートされています。HTML5 Canvas 2D は、JavaScript のキャンバス上の < canvas > tag で定義される API[14] を使用して、アプリケーション開発者がさまざまな 2D 操作を起動することを許します。このような操作には、イメージ操作、線などのベクター・グラフィックの描画、テキスト・レンダリングなどが含まれます。これらすべては、ゲーム、フォトアルバム、ビジュアル編集ツールなどの一般的な利用手順のかなりに及ぶため無くてはならない機能です。

HTML5 Canvas 2D とベンチマーク

イメージ操作の多くは重い処理のシナリオで行われ、ユーザー体験を支配しているため、前述した Angry Birds の HTML5 バージョンなどの例を含む大部分のゲームにおいて、イメージ関連の HTML5 Canvas 2D APIは特に重要です。

その結果、いくつかの一般に入手可能なベンチマークは、これらの利用シナリオをシミュレートして定量的にパフォーマンスを測定するように作られています。Microsoft社の FishIETank[15] は、最も良く利用されるベンチマークのひとつであり、多くの出版物やサイトでスマートフォンやタブレット向けのパフォーマンス指標として参照されています。オリジナルのFishIETank はさまざまなキャンバス・サイズに対応し、実装に乱数が使用されているためランタイムに多様性があります。私たちは、比較のため同じサイズ 700×480 に固定されたキャンバスで、複数の実行の間に一貫性のある結果を得るため、若干の修正対応を行っています。以降、記事中で具体的な説明なしで FishIETank について触れる場合、オリジナルではなく修正バージョンを指しています。

GUIMark3[16] は、業界で良く利用されるもう一つのベンチマークです。これには、FishIETank と同様にイメージ操作に特化した2つのテストケースが含まれています。さらに、円の描画とは異なりイメージに触れることなくベクター演算を行うテストケースが含まれます。

これら2つのベンチマークとは若干異なる、いくつかのAPIレベルの小規模なテストケースで構成される Canvas_Perf[17] ベンチマークがあります。これはHTML5 Canvas 2D APIの多くをカバーします。 それは、FishIETank や GUIMark3 から呼び出される1-2個の典型的なAPIではなく、一連のAPIのパフォーマンスを評価します。

Android 4.0 における HTML5 Canvas 2D の実装

HTML5 Canvas 2D のコンセプトを理解するのは容易ですが、Web ランタイムの複雑さのため基礎となる実装には多くの構成要素が関連し、実行フローは複数のプロセスやスレッドに渡ります。図1は Android 4.0 の標準ブラウザーにおける HTML5 Canvas 2D の高レベル実装を示します。

Android 4.0 ブラウザーにおける HTML5 Canvas 2 D のデフォルト実装

1: Android 4.0 ブラウザーにおける HTML5 Canvas 2 D のデフォルト実装 (出典: Intel Corporation, 2012)

標準 Android ブラウザーには3つの異なるワーカー、WebViewCore スレッド、WebViewMain スレッド、そして TextureGenerator スレッドがあります。各スレッドは異なる目的を果たします。

  • WebViewCore スレッドは、Android のグラフィック・エンジンである Skia[18] から送られる 2D 操作を利用してコンテンツを生成します。現在、Android の Skia はこの操作の後工程で CPUを使用しますが、これはHTML5 Canvas 2D に関連する演算も CPU で行われることを意味します。
  • WebViewMain スレッドは UI イベントをディスパッチし、システムディスプレイに表示するため複数のレイヤーで生成されたコンテンツを1つのイメージにマージします。後者のプロセスはコンポジションとして知られ、Android 4.0 以降では UI レスポンスを改善するため大部分が GPU にオフロードされます。
  • CPU によって生成されたコンテンツは GPU で合成されなければならないため、TextureGenerator スレッドは、CPU メモリーにあるビットマップイメージを GPU が利用可能なテクスチャーに変換する役割を持ちます。このような変換には時間がかかることから、オーバーヘッドを減らすためイメージはタイルと呼ばれる断片に分割され、更新されたタイルのみが必要に応じて変換されます。

私たちの分析によると、デフォルトの実装では少なくとも2つの欠点が明らかになっています。まず、CPU は拡大縮小や回転といった典型的なイメージ操作でコンテンツを生成するには GPU に比べあまりにも非効率です。次に、テクスチャー生成における CPU と GPU 間のデータ交換のオーバーヘッドは、無視できないほど大きなものです。私たちの分析では、インテル Atom ベースのモバイル・プラットフォームの 20% 以上の CPU 利用率は、これに関連するメモリーコピーに消費されます。

HTML5 Canvas 2D のグラフィック・アクセラレーション

HTML5 Canvas 2D のグラフィック・アクセラレーションは、前述の問題に対処する健全なアプローチです。GPU でコンテンツを描画することで、コンテンツ生成のパフォーマンスを向上させ、GPU 側にデータが置かれるためメモリーコピーのほとんどを排除できるでしょう。改善された実装を図 2 に示します。クロミウム(Chromium)とHTML5 ビデオの実装に触発され、私たちは他の基本WebコンテンツからHTML5 Canvas 2D を分離して、HTML5 ビデオのようにスタンドアローンのレイヤーとして扱います。この変更により、このキャンバス・レイヤーは、Skia CPU バックエンドを GPU バックエンドで置き換えることが可能となり、GPU はより効率良く、そしてテクスチャーを生成することなく直接コンテンツを描画できます。

HTML5 の Canvas 2D をアクセラレートするためハードウェアを利用して最適化

2: HTML5 の Canvas 2D をアクセラレートするためハードウェアを利用して最適化 (出典: Intel Corporation, 2012)

予想通り、この実装は重いイメージの HTML5 Canvas 2D ベンチマークで大幅にパフォーマンス向上をもたらします。インテル Atom プラットフォームでは、修正された FishIETank のFPS(1秒当たりのフレーム数)は元の3倍ほどになりました。

しかし、Canvas_Perf ベンチマークの一部の API では、70% のパフォーマンス低下が観測されました。分析の結果は、GPU によるアクセラレーションが常にすべての HTML5 Canvas 2D API で最速の方法ではないことを示しています。Skia CPU バックエンドは、特定の状況で GPU のバックエンドよりも優れています:

  • イメージ以外の操作。複数の頂点を含むベクター操作は、それをサポートする適切な 2D グラフィック・ユニットが存在しない場合、GPU では非常に時間がかかることがあります。
  • CPU によってアクセスされたイメージデータを必要とするGetImageData() などの API があります。もしそれが GPU によってアクセラレートされると、多くの場合 GPU ははじめに CPU と同期し CPU にデータをコピーする必要があるため、パフォーマンス低下の原因となります。

これが、Web コンテンツ全体に GPU アクセラレーションを適用せず、HTML5 Canvas 2D を分離する理由の一つです。

非効率なシナリオでもペナルティーを受けることなくイメージ操作のグラフィック・アクセラレーションの恩恵を受けるため、私たちは一定のヒューリスティックにより動的に CPU と GPU の経路を切り替えるメカニズムを設計そして実装しました。

図3に示すように、各フレームの実行はパフォーマンス指標やHTML5 Canvas 2D API リストのようなヒントを生成します。次のフレームでは、これらのヒントを基に事前定義されたルールに従って GPU と CPU のどちらを介する適切なパスが選択されます。最初のフレームはヒントが存在しないため、常に CPU のパスを通過します。

HTML5 Canvas 2D のための GPU と CPU の動的な切り替え

3: HTML5 Canvas 2D のための GPU と CPU の動的な切り替え(出典: Intel Corporation, 2012)

現在のルールはかなりシンプルかつ保守的で、Android 4.0 のデフォルト実装と比べてリグレッションすることなく簡単なソリューションを提供することを目的としています。次の要件がすべて満たされた場合に、フレームは GPU パスを通過します:

  • システムがコンポジットに GPU を利用しない;
  • グラフィック・コンテキストは初期化されている;
  • 少なくとも1つのイメージ操作が呼び出される;
  • GPU に非効率な API が呼び出されていない。例えば、GetImageData() や いくつかの(すべてではない)ベクター API が無いこと。
  • CPU パスから GPU へ切り替えた後、それ以上 CPU パスにフォールバックしない。

最後のルールは、GPU パスは一度切り替えれば十分だと判断したため、フォールバック・ソリューションとしてこのルールに基づいた実装を検討しています。これは非常に保守的であり、将来に向けて改善の余地があります。何らかの理由で実行を CPU にフォールバックしても、以降のフレームで再び GPU アクセラレーションを再開することが適切である場合があります。スマートでより積極的なルールを設計中であり、将来の作業として残されています。

グラフィック・アクセラレーションと CPU フォールバックの影響

図4 と 図5 は、インテル Atom ベースのデバイスにおける Canvas_Perf ベンチマークの影響を示しています。図4は、純粋なGPU ソリューションにおいて hline と vline API で 70% 遅くなり、イメージ関連の操作では 5 倍高速あることを示しています。図5では、フォールバック・メカニズムを適用することで、パフォーマンスの低下は解決され、イメージ操作ではさらにパフォーマンスが向上していることが分かります。

図5では、CPU のフォールバック・パスが Skia CPU バックエンドを実装した Android 標準ブラウザーのソリューションよりも高速であることが注目に値します。これは、HTML5 Canvas 2D をスタンドアロン・レイヤーとして分離したことで、CPU へフォールバックした後メモリーコピーやオーバーヘッドを排除できたことによります。

図6 と図7 は、FishIETank と GUIMark におけるパフォーマンスの影響を示しています。最大3倍のFPS の向上とCPU 利用率の 50% 低下が同時に観測できました。

純粋なグラフィック・アクセラレーションのパフォーマンス

4: 純粋なグラフィック・アクセラレーションのパフォーマンス(出典: Intel Corporation, 2012)

フォールバックを伴うグラフィック・アクセラレーションのパフォーマンス

5: フォールバックを伴うグラフィック・アクセラレーションのパフォーマンス(出典: Intel Corporation, 2012)

CPU 利用率の減少

6: CPU 利用率の減少(出典: Intel Corporation, 2012)

FPS の改善

7: FPS の改善(出典: Intel Corporation, 2012)

IA32 における DFG JIT

JIT は言語エンジンのランタイム・パフォーマンスを劇的に向上させる実績のある技術です。JavaScript は、動的言語として、高度な JIT 最適化を適用することに注目します。例えば、型は実行中に変更することができ、静的に決定されないようなことです。しかし、高い精度の型情報に基づいた先進的な最適化のほとんどは、ここに適用することはできません。その結果、効率良いオブジェクト・プロパティーへのアクセス、型のプロファイルと推測、そしてホットスポットの最適化をサポートするスタック上での置き換え(OSR)メカニズムや推測の失敗による最適化の取り消しなどを含む多くの特殊処理が必要になります。

JavaScriptCore における JIT 技術

JSC (JavaScriptCore)内部には2つのJITがあり、WebKit のデフォルトの JavaScript エンジンです。

  • ベースライン JIT: ベースライン JIT は、動的言語向けに古典的なインライン・キャッシュ最適化を除く複雑な最適化を行うことなく JSC バイトコードからネイティブコードを生成するコンパイル速度に最適化されています。多くの既存の Web サイトでは、頻繁に JavaScript を実行することなく高速なページ読み込みを行うにはこのような軽量な JIT が向いています。
  • DFG JIT: DFG JIT は、コンパイル速度のトレードオフとより高速なコードを生成のため、高度に最適化された JIT です。ベースライン JIT からの型プロファイルのフィードバックに基づいて型を推測し、JSC バイトコードから SSA 形式の DFG IR (中間コード)を生成します。プラットフォーム向けの最適化は、型推論、ローカル CSE (共通部分式の排除)、ローカル・レジスター割り当てなどが含まれ、IR からネイティブコードへの変換時に行われます。

JSC は、2つの JIT 間の動的な切り替えに階層モデルを利用します。JavaScript は、実行前にベースライン JIT で汎用ネイティブコードにコンパイルされます。汎用コードの実行中、プロファイラーはホットスポット情報と型情報を収集します。メソッドやループがホットスポットであると想定されると、DFG JIT は型推論に基づき最適化されたコードを生成するために起動されメソッドを再コンパイルします。投機が失敗する可能性があります。そのような場合、最適化の取り消しが起こりエンジンは一般実行にフォールバックします。JSC の JIT 基盤を図8に示します。

JSC JIT 基盤

8: JSC JIT 基盤(出典: Intel Corporation, 2012)

2012 年 3 月以降、JSC はMac OS と iOS の3層VM(仮想マシン)となり、ベースライン JIT の下に LLint (Low Level Interpreter)と呼ばれる他の階層を導入したことは注目に値します。

32 ビット Linuxにおける Intel® Atom™ のJavaScriptCore

DFG JIT が最初に登場した時、64ビット版のみが提供されていたため、32ビット・モバイルシステム上のJavaScript による重い Web アプリケーションはその恩恵を受けることができませんでした。例えば、Kraken JavaScript ベンチマーク・スイート[20] は、リッチな Web アプリケーションから抽出されたオーディオとイメージ処理向けのテストケースで構成され、DFG JIT を使用しない JSC はLinux が動作するインテル Atom プラットフォームで、Google V8 よりも 2.5 倍低速でした。したがって、私たちはこれらのプログラムをさらに効率良く処理するため、さらに最適化を行う必要があり、DFG JIT はこの目的に適しています。さらに、階層コンパイルモデルにより、ベースライン JIT は最小限のコンパイル・オーバーヘッドのため十分シンプルなままでした。これらすべての事実は、DFG JIT 技術をより多くのプラットフォームに展開することを示します。私たちの最初のターゲットは IA32 Linux です。

DFG JIT を IA32 に適用する

通常の JavaScript エンジンでは、いくつかの特殊データ形式は、オブジェクトへのポインター、整数、倍精度、ブール値、未定義データとNULL値を含む様々な JavaScript 値を表現するために定義されています。特殊フォーマットされたものをボックス化(boxed)された JSValue と呼び、元の値をボックス化されていない(unboxed)と言われます。JSC は、それぞれ 64 ビットと 32 ビット・プラットフォーム向けに2つの異なるデータ形式を持っています。両方のフォーマットが JSValue を表現するため、64ビット長のデータを使用しますが、ビットの表記法は異なります。

図9に示すように、32ビット・プラットフォームでは、 JSValue の上位32ビットは、型を示すタグとして使用され、下位32ビットで値が表現されます。64ビットで表現される倍精度はこれに当てはまりません。倍精度以外の値では未使用の NaN 空間を利用します。

図10に示すように、64ビット・プラットフォーム向けのデータ・フォーマットは同様に未使用の NaN 空間を利用しますが、上位16ビットで型を表現します。

32ビット・プラットフォームのJSCデータ形式 64ビット・プラットフォームのJSC データ形式

9: 32ビット・プラットフォームのJSCデータ形式
(出典: Intel Corporation, 2012)

10: 64ビット・プラットフォームのJSC データ形式
(出典: Intel Corporation, 2012)

このような背景を考慮すると、32ビット・プラットフォームにおいて DFG JIT を有効にする際の課題は、DFG JIT が全く異なるデータ形式を認識できるようにすることです。 残念なことに、ボックス化された JSValue を操作するため、同じロジックを2度記述しなければなりません。64ビット向けはすでに存在しているのに、32ビットが追加されたため同じことをしなければならなくなりました。一方、DFG JIT は型推論 JIT であり、すでにある多くの操作は、ボックス化されていない値に対して適用できるので幸運といえるでしょう。

x64 と比較して x86 の大きな問題の一つは、レジスター不足です。x86 で利用可能な GPR (汎用レジスター)は 8 個しかありません。JSC では、そのうち3つが特殊な目的のため予約されており、利用できるレジスターは5個しか残っていません。x86 のレジスター不足に対処するため、ボックス化されていない32ビット値を推測して表現する多くの値を持つ必要があります。例えば、64ビットにおいて32ビットブール値の推測は異なります(ボックス化された JSBoolean を2 つの32ビット GPR レジスターに保持する代わりに、ボックス化されていないブール値を保持するため1つの32ビット GPR を使用します)。この設計方針は、パフォーマンスだけでなくレジスターを節約するため採用されました。

私たちは JS 値を持っている場合、時により効率良いコードを生成できるように JS 値が特定の型であることを推測する必要があります。これには必然的にボックス化と非ボックス化を伴います。値がレジスターにあるような単純なケースを想定すると、JS 値は64ビット長であるため、32ビット・プラットフォームではこのJS値を表現するには2つの32ビットレジスターが必要です(1つは値、もう1つはタグ)。JS 整数、ブール値、またはポインターを非ボックス化するのは、単に値を保持するレジスターを採用するだけなので容易です。同様に、整数、ブール値、そしてポインターをボックス化するには、タグレジスターに適切なデータを保持します。事を複雑にするのは、 JS 倍精度とボックス化された倍精度を変換する方法です。JS の倍精度は2つの汎用レジスターに格納され、ボックス化された倍精度は1つの浮動小数点レジスターに格納されます。この変換を行う簡単な手法は、メモリーを介してデータを交換する方法ですが、パフォーマンスは非常に低下します。一方、非ボックス化倍精度データがXMMレジスターに格納されている場合、私たちは SSE2 命令によるパックデータのサポートを活用して効率良く変換できます。倍精度のボックス化と非ボックス化は、以下のシーケンスで行えます。

movd xmm0, eax
psrlq 32, xmm0

movd xmm0, edx

コード1: 倍精度値をボックス化
出典: Intel Corporation, 2012

movd eax, xmm0
movd edx, xmm1
psllq 32, xmm1
por xmm1, xmm0

コード2: JS 倍精度の非ボックス化
出典: Intel Corporation, 2012

この例では、eax レジスターには JS 倍精度が保持され、 edx レジスターにはそのタグが保持されることを仮定しています。さらに、xmm0 レジスターは非ボックス化倍精度値を保持し、xmm1 レジスターは一時レジスターとして使用されます。この例の JS 倍精度と非ボックス化倍精度間の変換では、メモリーアクセスは必要ありません。実証データとして、私たちはこの手法で  IA32 上の Kraken ベンチマークを 77% 高速化できました。コンパイル時に JS 値が JS 倍精度であることを知っていれば、2つの GPR に代わりに直接 FPR (浮動小数点レジスター)で表現し、倍精度の変換を向上できるかもしれません。しかし、それには DFG のコード生成ロジックが複雑になる可能性があります。

通常の DFG の JIT コード生成に加え、異なるデータ形式は推測の失敗による最適化の取り消しの要因となります。切り替えられた汎用コードは、常にボックス化された JS 値がメモリーにあることを想定します。しかし、実際には、DFG JIT コードはメモリーとレジスター両方で非ボックス化された値を生成することができます。そのため、汎用コードにフォールバックする時は、メモリーとレジスター間で必要なデータのボックス化とデータ転送を行う必要があります。

x86 の呼び出し規約はx64 と同一ではなく、x86 上のオペレーティング・システム向けの規約は異なります。そのため、私たちは JIT コードによって呼び出されるランタイムヘルパー関数を用意して、DFG JIT を異なる呼び出し規約に対応させる必要があります。私たちは、現在ベースライン JIT でサポートされる fastcall とは異なる cdecl 呼び出しを x86 DFG でサポートしています。 ヘルパー関数呼び出しインターフェイスも、容易に異なる呼び出し規約をサポートできるように、コミュニティーの助力を得て再設計されています。

IA32 における DFG JIT の影響

図11は、DFG JIT によるパフォーマンス向上を明確に示しています。IA32 の Kraken ベンチマークでは、最終的に2倍近い向上があり(2011年のコードを基にしたものでは)、最適化を完了しました。さらに、2011年11月から2012年3月の間、コミュニティーとの最適化の協業により、DFG JIT の結果を上回る性能向上を達成できました。

IA32 上のJSC パフォーマンス

11: IA32 上のJSC パフォーマンス(出典: Intel Corporation, 2012)

まとめと今後の展開

HTML5 は今後の Web アプリケーションの必然的な傾向です。それだけでなくパフォーマンス面では課題を残しながら、巨大なビジネスチャンスをもたらします。したがって、Web ランタイムの最適化は、HTML5 を採用する上で不可欠なものです。この記事ではインテル Atom ベースのプラットフォームで顕著なパフォーマンス向上を達成する2つの重要な技術、レンダリング・エンジンと JavaScript エンジンにおけるグラフィック・アクセラレーションとJIT について説明しました。

いくつかの改善が今後の課題として視野に入れられています:

  • “HTML5 Canvas 2D のグラフィック・アクセラレーション” 節で述べたように、CPU と GPU パスを切り替えにおけるより積極的なルールを開発中です。私たちは、新しい設計ではグラフィック・アクセラレーションの可能性を最大限に引き出し、HTML5 Canvas 2D のパフォーマンスを新たな次元に引き上げることを確信しています。
  • 私たちは同様に Skia バックエンドを改善するいくつかのアイディアを持っています。これは、GPU 上のベクター関連の API で非効率な実装を軽減するでしょう。
  • JSC JavaScript エンジンに関しては、DFG JIT の IR はまだ非常にシンプルであり、いくつかの高度な機能を欠いています。私たちは、これを改善するためコミュニティーのエンジニアと協業しています。より強力な実装では、JSC上の多くの JIT 最適化を実装するのは容易であると考えています。

グラフィック・アクセラレーションと高度な JIT は、高い可能性を秘めた魅力的な技術であるため、私たちはそれらを CSS3 や WebGL のような他の新しい Web 技術へ実装可能であるかどうか模索しています。

参考文献

[1] HTML5 specification (draft 25), World Wide Web Consortium (W3C), May 2011. http://www.w3.org/TR/2011/WD-html5-20110525/
[2] Processor family for mobile segments, Intel. http://www.intel.com/content/www/us/en/processors/atom/atom-processor.html
[3] Gartner, 2011. http://www.gartner.com/it/page.jsp?id=1826214
[4] HTML5 Angry Birds, Rovio Entertainments Ltd. http://chrome.angrybirds.com/
[5] Google to use HTML5 in Gmail. http://www.computerworld.com/s/article/9178558/Google_to_use_HTML5_in_Gmail?taxonomyId=11& pageNumber=2
[6] Brad Neuberg, Google. Introduction to HTML5. http://googlecode.blogspot.com/2009/09/video-introduction-to-html-5.html
[7] Mobile operating system, Google. http://www.android.com/
[8] Open source project for browser and mobile OS, Google. http://www.chromium.org/
[9] A New Crankshaft for V8, Google. http://blog.chromium.org/2010/12/new-crankshaft-for-v8.html
[10] V8 JavaScript Engine. http://code.google.com/p/v8/
[11] V8 Benchmark Suite Version 6. http://v8.googlecode.com/svn/data/benchmarks/v6/run.html
[12] The WebKit Open Source Project. http://www.webkit.org/
[13] HTML Canvas 2D Context, World Wide Web Consortium (W3C). http://www.w3.org/TR/2dcontext/
[14] JavaScript Web API standards, World Wide Web Consortium (W3C). http://www.w3.org/standards/webdesign/script
[15] FishIETank workload, Microsoft. http://ie.microsoft.com/testdrive/Performance/FishIETank/Default.html
[16] Browser graphics benchmark, Sean Christmann. http://www.craftymind.com/guimark3/
[17] Browser graphics benchmark, Hatena. http://flashcanvas.net/examples/dl.dropbox.com/u/1865210/mindcat/canvas_perf.html
[18] Open project as 2D graphics engine, Google. http://code.google.com/p/skia/
[19] SunSpider JavaScript Benchmark. http://www.webkit.org/perf/sunspider/sunspider.html
[20] Kraken JavaScript Benchmark. http://kraken-mirror.googlecode.com/svn/trunk/kraken/hosted/index.html

著者略歴

Jonathan Ding (jonathan.ding@intel.com) は、インテルのソフトウェア&サービス・グループのエンジニアです。彼は、ブラウザー、Web ランタイム、HTML5、および関連するフレームワークを専門としています。

Yuqiang Xian (yuqiang.xian@intel.com) は、インテルのソフトウェア&サービス・グループのエンジニアです。彼は、コンパイラーと仮想マシンに興味を持っています。

Yongnian Le (yongnian.le@intel.com) は、インテルのソフトウェア&サービス・グループのエンジニアです。彼は、現在Android モバイル・プラットフォームにおけるブラウザー関連の分析と最適化に注目しています。

Kangyuan Shu (kangyuan.shu@intel.com) は、インテルのソフトウェア&サービス・グループのエンジニアです。彼は、Android とグラフィック・サブシステムに興味を持っています。

Haili Zhang (haili.zhang@intel.com) は、インテルのソフトウェア&サービス・グループのエンジニアです。 彼は、HTML5とオープンソース Web プラットフォーム関連のアプリケーション・フレームワークを専門としています。

Jason Zhu (jason.zhu@intel.com) は、インテルのソフトウェア&サービス・グループのエンジニアです。彼は、高度な新興Webブラウザーと革新に興味を持っています。

関連記事