JavaScript の仕組みを理解し、V8 エンジンを詳しく理解し、最適化されたコードを作成します
javascriptこのコラムでは、詳細な V8 エンジンと最適化されたコードの作成について紹介します
関連する無料学習の推奨事項: javascript(ビデオ)
概要
JavaScript エンジンは、JavaScript コードを実行するプログラムまたはインタープリターです。 JavaScript エンジンは、標準インタプリタとして、または JavaScript をバイトコードにコンパイルする何らかの形式のジャストインタイム コンパイラとして実装できます。
JavaScript エンジンを実装する人気のあるプロジェクトのリスト:
- V8 — Google によって開発され、C
- ## で書かれたオープン ソースRhino — Mozilla Foundation によって管理され、オープン ソースで、完全に Java で開発されています
- SpiderMonkey — Netscape Navigator をサポートする最初の JavaScript エンジンであり、現在 Firefox## で使用されています #JavaScriptCore
- — オープン ソース、Nitro として販売、Apple が Safari 用に開発 KJS
- — KDE 用のエンジン。元々は Harri Porten によって開発されました。 KDE プロジェクト Konqueror Web ブラウザ開発 Chakra
- (JScript9) — Internet Explorer Chakra
- (JavaScript) Microsoft Edge Nashorn
- (Oracle Java Language and Tools Group によって作成された OpenJDK の一部) ##JerryScript — モノのインターネット用の軽量エンジン
- # #なぜ V8 エンジンが作成されたのですか? Google によって構築された V8 エンジンはオープンソースであり、C で書かれています。このエンジンは Google Chrome で使用されますが、他のエンジンとは異なり、V8 は人気のある Node.js でも使用されます。
V8 は元々、Web ブラウザーでの JavaScript 実行のパフォーマンスを向上させるために設計されました。速度を上げるために、V8 ではインタープリターを使用する代わりに、JavaScript コードをより効率的なマシン コードに変換します。 SpiderMonkey や Rhino (Mozilla) などの多くの最新の JavaScript エンジンと同様に、JIT (ジャストインタイム) コンパイラーを実装することで、JavaScript コードを実行時マシン コードにコンパイルします。ここでの主な違いは、V8 はバイトコードや中間コードを生成しないことです。 V8 には 2 つのコンパイラがありました
V8 の 5.9 バージョンがリリースされる前、V8 エンジンは 2 つのコンパイラを使用していました:
full-codegen — 1 つ シンプルで非常に高速シンプルで比較的遅いマシンコードを生成するコンパイラ。 クランクシャフト - 高度に最適化されたコードを生成する、より洗練された (ジャストインタイム) 最適化コンパイラー。- V8 エンジンは内部でも複数のスレッドを使用します。
- #クランクシャフトが最適化できるように、多くの時間を費やしたことをランタイムに伝えるプロファイラー スレッド
- 一部のスレッドはガベージ コレクターを処理します
- JavaScript コードが初めて実行されるとき、V8 は完全な codegen コンパイラーを使用して、解析された JavaScript を変換せずにマシン コードに直接変換します。これにより、マシンコードの実行を非常に迅速に開始できるようになります。 V8 は中間バイトコードを使用しないため、インタプリタが必要ないことに注意してください。
- コードがしばらく実行されると、分析スレッドはどのメソッドを最適化する必要があるかを決定するのに十分なデータを収集しました。
隠しクラス
JavaScript はプロトタイプベースの言語です。クラスとオブジェクトはクローン作成プロセスを使用して作成されません。 JavaScript は動的プログラミング言語でもあります。つまり、インスタンス化後にオブジェクトにプロパティを簡単に追加したり、オブジェクトからプロパティを削除したりできます。
したがって、属性値 (またはこれらの属性へのポインタ) は、各バッファ間の固定オフセットを使用して、連続したバッファとしてメモリに保存できます。オフセットの長さは属性タイプに基づいて簡単に決定できますが、 JavaScript では不可能な、実行時にプロパティ タイプを変更できます。
辞書を使用してメモリ内のオブジェクトのプロパティの場所を見つけるのは非常に効率が悪いため、V8 では別のアプローチ、つまり隠しクラスを使用します。非表示クラスは、実行時に作成される点を除けば、Java などの言語で使用される固定オブジェクト (クラス) と同様に機能します。さて、実際の例を見てみましょう:
「new Point(1,2)」呼び出しが発生すると、V8 は「C0」という名前の付いた非表示の種類を作成します。
Point にはプロパティが定義されていないため、「C0」は空です。
最初のステートメント "this.x = x" が ("Point" 関数内で) 実行されると、V8 は "C0" に基づく "C1" という名前の 2 番目の隠しクラスを作成します。 「C1」は、プロパティ x が見つかるメモリ内の位置 (オブジェクト ポインタを基準とした) を表します。
この場合、 "x" はオフセット 0 に格納されます。つまり、メモリ内のポイント オブジェクトを連続バッファーとみなすと、最初のオフセットが属性 "x" に対応します。また、V8 では、属性「x」がポイント オブジェクトに追加された場合、隠しクラスが「C0」から「C1」に切り替わる必要があることを示す「クラス変換」で「C0」を更新します。以下の点オブジェクトの非表示クラスは「C1」になりました。
#新しいプロパティがオブジェクトに追加されるたびに、古い非表示クラスは、新しい非表示クラスを指す変換パスで更新されます。非表示クラスのキャストは、同じ方法で作成されたオブジェクト間で非表示クラスを共有できるため、重要です。 2 つのオブジェクトが非表示クラスを共有し、同じプロパティがそれらに追加される場合、変換により、両方のオブジェクトが同じ新しい非表示クラスとそれに付属するすべての最適化コードを確実に受け取ります。
ステートメント「this.y = y」が実行されるとき (「this.x = x」ステートメントの後の「Point」関数内)、同じプロセスが繰り返されます。
「C2」という名前の新しい非表示クラスが作成されます。プロパティ「y」が Point オブジェクト (プロパティ「x」がすでに含まれている) に追加される場合、クラス変換が「C1」に追加されます。 " の場合、非表示クラスを「C2」に変更し、ポイント オブジェクトの非表示クラスを「C2」に更新する必要があります。
インライン キャッシュは、同じタイプのオブジェクトが非表示クラスを共有することが重要である理由でもあります。同じタイプで異なる非表示クラスの 2 つのオブジェクトを作成する場合 (前の例で行ったように)、2 つのオブジェクトが同じタイプであっても、対応する非表示クラスはそのオブジェクトに対応するため、V8 はインライン キャッシュを使用できません。プロパティには異なるオフセットが割り当てられます。
2 つのオブジェクトは基本的に同じですが、「a」プロパティと「b」プロパティは異なる順序で作成されます。
マシンコードへのコンパイル
水素グラフが最適化されると、クランクシャフトはそれをリチウムと呼ばれる下位レベルの表現に縮小します。ほとんどの Lithium 実装はアーキテクチャ固有です。レジスタ割り当ては、多くの場合、このレベルで発生します。
最後に、Lithium はマシンコードにコンパイルされます。次に、OSR: オンスタック置換です。明示的な長時間実行メソッドのコンパイルと最適化を開始する前に、スタックの置換を実行することがあります。 V8 は、スタックの置換をゆっくりと実行して再び最適化を開始するだけではありません。代わりに、実行中にすべてのコンテキスト (スタック、レジスタ) を変換し、最適化されたバージョンに切り替えます。 V8 では最初にコードがインライン化されることを考慮すると、これは非常に複雑なタスクです。それが可能なエンジンはV8だけではありません。
逆最適化と呼ばれる安全対策があり、エンジンが無効であると想定して逆の変換を行い、最適化されていないコードを返します。
ガベージ コレクション
ガベージ コレクションの場合、V8 は従来のマーク アンド スイープ アルゴリズムを使用して古い世代をクリーンアップします。マーキングフェーズでは JavaScript の実行を停止する必要があります。 GC コストを制御し、実行をより安定させるために、V8 は増分マーキングを使用します。つまり、ヒープ全体をウォークしてすべての可能なオブジェクトをマークしようとするのではなく、ヒープの一部をウォークして通常の実行を再開します。次の GC 停止は、前回のヒープ ウォークが中断したところから継続されます。これにより、通常の実行中に非常に短い一時停止が可能になります。前述したように、スキャン フェーズは別のスレッドによって処理されます。
最適化された JavaScript の記述方法
- オブジェクト プロパティの順序: 隠しクラスと後続の最適化をコードで共有できるように、オブジェクト プロパティを常に同じ順序でインスタンス化します。 。
- 動的プロパティ: インスタンス化後にオブジェクトにプロパティを追加すると、非表示クラスの変更が強制され、以前に非表示クラスによって最適化されたすべてのメソッドの実行が遅くなるため、すべてのオブジェクトを変更することが重要です。プロパティはコンストラクターで割り当てられます。
- メソッド: 同じメソッドを繰り返し実行するコードは、複数の異なるメソッドを 1 回だけ実行するコードよりも高速に実行されます (インライン キャッシュのため)。
- 配列: キー値が自己増加する数値ではない疎配列は避けてください。また、すべての要素を格納しない疎配列はハッシュ テーブルになります。このような配列内の要素へのアクセスにはコストがかかります。また、大きな配列を事前に割り当てることは避けてください。需要に応じて成長する方が良いでしょう。最後に、キーが疎になってしまうため、配列から要素を削除しないでください。
- タグ値: V8 は 32 ビットを使用してオブジェクトと値を表します。値は31ビットなので、1ビットを使ってオブジェクト(flag = 1)かSMI(SMall Integer)と呼ばれる整数(flag = 0)かを区別します。次に、数値が 31 桁より大きい場合、V8 は数値をボックス化して double に変換し、その数値を保持する新しいオブジェクトを作成します。 JS オブジェクトに対する負荷の高いボックス化操作を避けるために、可能な限り 31 ビットの符号付き数値を使用してください。
Ignition と TurboFan
2017 年初めの V8 5.9 のリリースで、新しい実行パイプラインが導入されました。この新しいパイプラインにより、実際の JavaScript アプリケーションのパフォーマンスが大幅に向上し、メモリが大幅に節約されます。
新しい実行フローは、Ignition (V8 のインタープリター) と TurboFan (V8 の最新の最適化コンパイラー) に基づいて構築されています。
V8 5.9 のリリース以来、V8 チームは新しい JavaScript 言語機能とこれらの機能に必要な最適化に追いつくのに苦労してきたため、V8 チームは完全なコード生成とクランクシャフトを使用しなくなりました (2010 年以降) V8 テクノロジーによってサービスされます)。
これは、V8 が全体的によりシンプルで保守しやすいアーキテクチャになることを意味します。
関連する無料学習の推奨事項:php プログラミング (ビデオ)
以上がJavaScript の仕組みを理解し、V8 エンジンを詳しく理解し、最適化されたコードを作成しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









HTML の表の境界線に関するガイド。ここでは、HTML でのテーブルの境界線の例を示しながら、テーブル境界線を定義する複数の方法について説明します。

HTML マージン左のガイド。ここでは、HTML margin-left の概要とその例、およびそのコード実装について説明します。

これは、HTML でのネストされたテーブルのガイドです。ここでは、テーブル内にテーブルを作成する方法をそれぞれの例とともに説明します。

HTML テーブル レイアウトのガイド。ここでは、HTML テーブル レイアウトの値と例および出力について詳しく説明します。

HTML 入力プレースホルダーのガイド。ここでは、コードと出力とともに HTML 入力プレースホルダーの例について説明します。

HTML でのテキストの移動に関するガイド。ここでは、概要、マーキー タグが構文でどのように機能するか、および実装例について説明します。

HTML オンクリック ボタンのガイド。ここでは、それらの紹介、動作、例、およびさまざまなイベントでの onclick イベントについてそれぞれ説明します。
