Chrome V8はどのように機能しますか?そして、そもそもなぜJavaScriptはJITコンパイルされなかったのですか?


19

私は通訳者/コンパイラを研究してきましたが、その後、JITコンパイル、特にGoogle ChromeのV8 Javascript Engineに出会いました。

私の質問は-

  1. どのように標準の解釈より速くできますか?
  2. そもそもJITコンパイルが使用されなかったのはなぜですか?


私の現在の理解

  1. すべてのJavascriptプログラムはソースコードとして開始され、実行方法に関係なく、最終的にはマシンコードに変換されますJIT-CompilationInterpretation
    両方ともこのパスに従う必要があります。どのようにJIT-Compilationを高速化することができますか(また、AOT-Compilationとは異なり、JITは時間制約があるため)。

  2. JIT-CompilationはウィキペディアのJIT-Compilation Articleに基づいた比較的古いイノベーションのようです。

「最初に公開されたJITコンパイラは、一般的に1960年に McCarthyによってLISPで動作するとされています。」

「Smalltalkの(C。1983)たとえば、マシンコードへの変換は、オンデマンドで行われた。JITコンパイルの新たな側面を開拓し、その結果は後で使用するためにキャッシュされた。メモリが不足になった場合、システムはこのコードと再生成の一部を削除しますそれが再び必要になったとき。」

では、なぜJavascript が最初から解釈されたのですか?


私は非常に混乱しており、これについて多くの研究を行ってきましたが、満足のいく答えは見つかりませんでした。

とても明確で簡潔な回答をいただければ幸いです。また、通訳者、JITコンパイラなどについての追加説明が必要な場合は、それも歓迎します。


2
#2と#3は回答可能ですが、「Chrome V8エンジンの仕組み」資格なしでは広すぎる。唯一の正しい答えは、V8ソースコードへのリンクです。V8についてもっと具体的な質問をするつもりですか?(そうでない場合は、質問のその部分を削除するのが最善でしょう)
Ixrec

一目で、#1を求める私の唯一のポイントは、#2を理解することだったので、それを削除します。入力いただきありがとうございます。
アントンパラス

これは他の回答では言及されていませんが、JITのコンパイルは困難です。JITコンパイルに起因するエラーはエラーではなくセグメンテーションフォールトになるため、簡単なことではありません。コンソールでエラーをスローする代わりにプログラムがクラッシュします。はい、gdbに慣れている有能なCプログラマーにとって、これは問題ではありません。しかし、gdbに慣れているほとんどすべての有能なCプログラマーは、他のプロジェクトに取り組むための報酬を受け取ります。PerlやRubyなどの他の言語には、まだ主流のJITインタープリターがありません。
スリーブマン

ご参考までに。これについては、プログラミング言語の中核となる開発者/保守者の観点から話しています。数年の間、私はFeriteプログラミング言語を維持するために雇われました。希望リストの1つは、JITを実装することでした。それは決して起こりませんでした-私たちは代わりに行きました。Facebookがそれを実現するのに十分なお金を注ぎ込んでいるおかげで、PHPは最近JITコンパイラ(HVVM)を手に入れました。
スリーブマン

回答:


43

簡単な答えは、JITの初期化時間は長くなりますが、長い目で見ればはるかに高速であり、JavaScriptは本来長い目で見たものではありませんでした。

90年代には、Webサイトの典型的なJavaScriptはヘッダー内の1つまたは2つの関数になり、onclickプロパティなどに直接埋め込まれた少数のコードになりました。通常、ユーザーがとにかく大きなページの読み込み遅延を予期していたときに実行されます。非常に基本的なフォーム検証や、住宅ローンの利息計算などの小さな数学ユーティリティを考えてください。

必要に応じて解釈する方がはるかに簡単で、その日のユースケースに完全に適切なパフォーマンスを提供しました。長期的なパフォーマンスを必要とする場合は、フラッシュまたはJavaアプレットを使用しました。

2004年のGoogleマップは、JavaScriptを多用する最初のキラーアプリの1つでした。JavaScriptの可能性に目を見張るものでしたが、パフォーマンスの問題も浮き彫りにしました。GoogleはブラウザにJavaScriptのパフォーマンスを向上させるようにしばらく時間を費やし、最終的には競争が最高の動機付けになると判断し、ブラウザ標準テーブルで最高の座を獲得しました。その結果、ChromeとV8は2008年にリリースされました。Google Mapsが登場してから11年が経ち、JavaScriptがその種のタスクに不適切と見なされたことを覚えていない新しい開発者がいます。

機能があるとしましょうanimateDraggedMap。解釈に500ミリ秒、JITコンパイルに700ミリ秒かかる場合があります。ただし、JITコンパイル後、実際に実行するのに100ミリ秒しかかからない場合があります。90年代で、関数を1回だけ呼び出してからページをリロードする場合、JITはまったく価値がありません。今日でanimateDraggedMap何百または何千回も呼び出している場合、初期化時の余分な200ミリ秒は何もありません。ユーザーがマップをドラッグしようとする前に舞台裏で実行できます。


2

実行時に何が起こっているかを理解することで、コードを変更したり、コードの解釈を行ったりすることで、事前のコンパイル時よりも高速に実行したり、より適切にコンパイルしたりすることができます。

これについてはかなり言えることがあります-それはかなりの量の研究の主題です。ここで、違い理解する:従来のインタープリター、JITコンパイラー、JITインタープリター、AOTコンパイラーで与えられた答えと比較して、見劣りを書き始めたという私自身の説明


簡単に言えば、JavaScriptは最初はJIT向けにコンパイルも検索もされませんでした。なぜなら、それは決して複雑で重要なものになることを意図していないからです。

Java Script の本来の目的は、Webページ上のJavaアプレットにリンクすることでした。ボタンをクリックするか、フォームフィールドに値を入力し、Javaアプレットメソッドで作業する機能は、「JavaScriptコードからのアプレットメソッドの呼び出し」で確認できますJavaScriptを使用して、アプレットからJavaScriptコード呼び出す別の方法を使用することもできました。

JavaScriptの当初の意図は、アプレットとそれらを含むhtmlページをリンクすることでした。このような小さなタスクの場合、優れたパフォーマンスは必要ありません(パフォーマンスが必要な場合は、JITされたアプレットメソッドを呼び出します)。

NetscapeがJavaScriptを独自の言語として重要な作業を行い、開発のために推進するようになってから(Netscape Enterprise Serverのサーバー側JavaScriptを含む-偶然にコンパイルを事前に行っていた)、JavaScriptが深刻なターゲットとして明らかになりました。それを有用にするために必要なツールのためにそれから何年もかかりました。


1
いいえ、JavascriptはJavaとは関係ありません。また、JavaアプレットはJVMバイトコードです。
バジルスタリンケビッチ

@BasileStarynkevitch JavaScriptは、ハムレットページのJavaアプレットで動作するように設計されました。これは、HTML domとJavaオブジェクトに含まれるメソッドとの間の接着剤として機能します。これはJavaであり、Javaになることを意図したものではありませんでした。

JavaScriptは元々ECMAScript(またはそのようなもの)と呼ばれ、Javaとは何の関係もありませんでした。JavaScriptと呼ばれるようになった方法は、関心のある人たちの別の研究の主題です。これにより、今後混乱が生じます。
すぐに

1
@quickly_nowまだtc39.github.io/ecma262
caub

はい。そして、奇妙な理由で、私がそれを上に指摘したとき、私はそれに対して支持されました!
すぐに今すぐ

1

JITはJavaScriptに対して高速です。変数のタイプがわからない場合、高速のマシンコードを生成することは不可能だからです。

型情報がない場合、計算は高価です。例えば、

x + y

xとyについて何も知らない場合は非常に複雑です。これらは、整数、倍精度、文字列、またはこの計算に副作用のあるオブジェクトです。静的型付けがないため、これは高価な計算です。

ジャストインタイムコンパイルでは、ランタイム情報を使用して、これをより高速な計算に変換できます。実行時に、V8は変数のタイプを追跡します。上記のコードが、たとえば文字列を使用して複数回実行される場合、コンパイラは文字列連結のためのはるかに単純な命令を実行できます。そのため、コンパイラはx + y、さまざまなタイプのxおよびyに分岐する大量のコードを実行する代わりにに達すると、文字列があるかどうかをすばやくチェックし、文字列を具体的に連結する数行のマシンコードのみを実行します。

たとえば、C ++では、変数を宣言する必要があるため、コンパイラはxとyの型を事前に知っています。そのため、コードを実行する前に文字列を連結するための最適化されたマシンコードを生成できます。


0

1)どのように標準の解釈よりも速くできますか? よく考えられた例は次のとおりです。ApplicationCompiledとApplicationInterpretedの2つのアプリケーションがあるとします。これらのプログラムはどちらもまったく同じことを行い、同じソースコードを共有します。ApplicationCompiledのコンパイルには6秒かかります。

シナリオAのタイミングは次のとおりであるとしましょう:

  • ApplicationCompiledの場合:4秒
  • ApplicationInterpretedの場合:12秒

したがって、合計でApplicationCompiledはシナリオAの実行に10秒かかり(6秒のコンパイル、4秒の実行)、ApplicationInterpretedの実行には合計で12秒かかります。私はあなたに示す特定の例を持っていません、そして、どのケースで上記が当てはまるかわかりません-それはまた、インタープリターとコンパイラーがどれだけインテリジェントであるかに大きく依存します。

明らかにこれは非常に単純化されていますが、同じ考えをJITのコンパイル/解釈に適用できます。次の質問は、「このブランチをJITコンパイルまたは解釈する必要があるかどうかを低コストでどのように判断するか」です。私はここでリーグから外れています:)

2)そもそもJITコンパイルが使用されなかったのはなぜですか? わかりませんが、JavaScriptのような最適化が難しい言語をこれらのような高度なテクニックを適用するために利用できる進歩のリソースと成熟度の問題にすぎないことを確認します。おそらく、下にぶら下がっている果物がたくさんあったでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.