jvm-backendのコンパイルと最適化に関する深い理解

この記事は読書ノートです

1.ジャストインタイムコンパイラ

ホットスポットコード
メソッドまたはコードブロックは特に頻繁に(再帰的に)実行されます。これらのコードはホットスポットコードと呼ばれます
。ホットスポットコードをローカルコードにコンパイルするバックエンドコンパイラはジャストインタイムコンパイラと呼ばれます。

記事の冒頭に挙げられたいくつかの質問:

1. HotSpot仮想マシンがインタープリターとリアルタイムコンパイラが共存するアーキテクチャを使用するのはなぜですか?

  • プログラムをすばやく起動して実行する必要がある場合、インタープリターは最初に役割を果たし、コンパイル時間を節約して、すぐに実行できます。
  • プログラムの開始後、時間が経つにつれ、コンパイラーは徐々に役割を果たし、ますます多くのコードをローカルコードにコンパイルします。これにより、インタープリターの中間的な損失を減らし、より高い実行効率を得ることができます。プログラム実行環境でメモリリソースの制限が大きい場合、インタプリタ実行を使用してメモリを節約できます。
  • インタープリターとコンパイラーは、多くの場合、互いに補完するために連携して動作します
    ここに画像の説明を挿入

2. HotSpot仮想マシンが2つ(または3つ)の異なるリアルタイムコンパイラを実装するのはなぜですか?
主に階層コンパイル用です。
階層コンパイル、インタープリター、クライアントコンパイラ、サーバーコンパイラが同時に動作する場合、ホットコードは複数回コンパイルされる可能性があります。クライアントコンパイラを使用して、より高いコンパイルを取得します。速度、サーバー側コンパイラを使用してより良いコンパイル品質を取得し、解釈および実行時、およびサーバー側コンパイラが複雑度の高い最適化アルゴリズムを使用する場合、クライアント側コンパイラがパフォーマンス監視情報を収集する追加のタスクを実行する必要がない単純な最適化を使用して、コンパイル時間を増やすことができます。

3.インタプリタを使用してプログラムが実行されるのはいつですか?コンパイラを使用して実行するのはいつですか?
ここに画像の説明を挿入

4.どのプログラムコードがローカルコードにコンパイルされますか?ローカルコードをコンパイルするには?
・複数回呼び出されるメソッド。・複数回実行されるループ本体。

コンパイルのターゲットオブジェクトは、メソッド本体全体であり、個別のループ本体ではありません。

最初のケースでは、メソッドによってトリガーされるコンパイルに依存しているため、コンパイラーはメソッド全体をコンパイルオブジェクトとして当然使用しますが、このコンパイルは、仮想マシンの標準のジャストインタイムコンパイルメソッドでもあります。

後者の場合、コンパイルアクションはループ本体によってトリガーされ、ホットスポットはメソッドの一部にすぎませんが、コンパイラはメソッド全体をコンパイルオブジェクトとして使用し、実行エントリのみを使用する必要があります(メソッドのいくつかのバイトコード命令から開始)実行)は少し異なり、コンパイル時に実行エントリポイントのバイトコード番号(バイトコードインデックス、BCI)が渡されます。メソッドの実行中にコンパイルが行われるため、このコンパイル方法は "On Stack Replacement"(OSR)と呼ばれます。つまり、メソッドのスタックフレームはスタック上にあり、メソッドは置き換えられます。

5.ジャストインタイムコンパイラのコンパイルプロセスとコンパイル結果を外部から確認するにはどうすればよいですか?

一部の実行中のパラメーターでは、FastDebugまたはSlowDebug最適化レベルのHotSpot仮想マシンをサポートする必要があります。製品レベルの仮想マシンはこれらのパラメーターを使用できません。
つまり、平均的な人は
手動で編集を見ることができない、または非公式の編集バージョン

2.アドバンスコンパイラ

1つのブランチは、プログラムが実行される前にプログラムコードをマシンコードの静的変換作業にコンパイルする従来のCおよびC ++コンパイラーに似ています。

もう1つのブランチは、元のジャストインタイムコンパイラーが実行時に実行する必要があるコンパイル作業をプリコンパイルして保存することです。次にこれらのコードに対して実行するとき(たとえば、共通ライブラリコードは、同じマシン上の他のJavaプロセスで使用されます)、直接ロードされます。是非ご利用ください。

Androidアウトブレイクの例は、初期のコンパイルの完全な使用であることがわかります

3.最適化テクノロジー

コンパイラー最適化テクノロジーは
主に4つのタイプを導入します。1.最終的な技術的最適化:メソッドのインライン化2.最も最先端の最適化テクノロジー:エスケープ分析3.言語非依存のクラシック最適化テクノロジー:一般的な部分式の除去4.言語関連のクラシック最適化テクノロジー:配列境界チェックの排除
メソッドのインライン化:
メソッドのインライン化は、ターゲットメソッドのコードをそのまま呼び出しを開始したメソッドに「コピー」し、実際のメソッド呼び出しを回避します。
Javaメソッドの場合、多くのメソッドが仮想メソッドであり、実行前に呼び出しの多態性の選択が不明であることの難しさがあります。この問題を解決するために、Java仮想マシンは型継承分析(CHA)と呼ばれるメソッドを導入しています。さまざまな状況でさまざまなメソッドが使用されます
。①非仮想メソッドの場合は、インライン化します。
②仮想メソッドであり、現在のプログラム状態で選択する対象バージョンがこのメソッドに1つしかない場合は、仮定することで「インラインでガード」できます。新しいタイプが将来ロードされる可能性があり、CHAの結論が変わるため、このインライン化は根本的な予測最適化であり、「エスケープドア」を予約する必要があります。
③仮想メソッドであり、選択するバージョンが複数ある場合は、インラインキャッシュを使用して、メソッド呼び出しのコストを削減します。これは、異なるバージョンの各メソッド呼び出しを記録することとして理解でき、次の呼び出し後にメソッドを判断するだけで済みます。採用されているバージョンはすぐにインライン化できます。
エスケープ分析:
これはコードを直接最適化する手段ではなく、他の最適化手段の基礎を提供する分析手法です。
オブジェクトがメソッドで定義されている場合、そのオブジェクトは外部メソッドによって参照される可能性があります。このメソッドはメソッドエスケープと呼ばれ、外部スレッドからもアクセスされます。これはスレッドエスケープと呼ばれます。エスケープなしからメソッドエスケープまで、スレッドエスケープまで、オブジェクトエスケープのさまざまなレベルを低から高へと呼びます。
オブジェクトがエスケープしない場合、またはエスケープの確率が非常に低い場合は、次の最適化を実行できます
。①スタックへの割り当て:このオブジェクトにJavaヒープ内のメモリを割り当てさせず、スタックに直接メモリを割り当てます。オブジェクトが占有するメモリ領域は、スタックフレームがポップされて破棄されます。
②スカラー置換:データを小さいデータに分解して表現することはできません。これはスカラーで、それ以外の場合は集計です。オブジェクトは典型的な総量です。オブジェクトがエスケープしない場合は、オブジェクトを逆アセンブルすることができ、プログラムのアクセス状況に応じて、そのメンバー変数を元の型に復元してアクセスできます。
③同期排除:エスケープしないと他のスレッドからアクセスされないため、本変数の同期対策をキャンセルすることができます。
一般的な部分式の除去:
計算された変数の場合、後続の呼び出しで結果を呼び出すことができ、変数の式が削除されます。
この最適化がプログラムの基本ブロックに限定されている場合は、ローカルの共通部分式の除去と呼ぶことができます;最適化の範囲は、グローバル共通部分式の除去と呼ぶことができる複数の基本ブロックをカバーしています。
データ境界チェックにより、
Javaは動的セキュリティ言語でなくなります。データにアクセスするたびに、上限と下限をチェックする必要がありますが、チェックごとに多くの実行時間を浪費する必要があります。したがって、暗黙的な例外処理が使用され、エラーが発生したときにのみチェックが実行されます。

公開された37元の記事 ウォンの賞賛6 ビュー4638

おすすめ

転載: blog.csdn.net/littlewhitevg/article/details/105567500