[Java仮想マシンのジャストインタイムコンパイラの詳細な理解] 1141コンパイラ最適化テクノロジ

I.概要

1.コンパイラの目的は、プログラムコードをローカルマシンコードに変換することですが、マシンコードを正常に変換できるかどうかは問題ではありません。出力コードの最適化の品質は、コンパイラが優れているかどうかを判断するための鍵です。 。

2.最適化技術の概要

1. OpenJDKの公式Wikiで、HotSpot仮想マシン設計チームは、ジャストインタイムコンパイラで使用される最適化手法の比較的包括的なリストをリストしています。
ここに写真の説明を挿入

ここに写真の説明を挿入

ここに写真の説明を挿入

2.ジャストインタイムコンパイラによるこれらのコードの最適化と変換は、Javaソースコードに直接ではなく、コードまたはマシンコードの中間表現に基づいています。

3.さまざまなコンパイラは、通常、インライン最適化を最適化シーケンスの先頭に置きます。

3、4つの代表的な最適化技術の学習

1.最も重要な最適化手法の1つ:メソッドのインライン化。

2.最も最先端の最適化テクノロジーの1つ:エスケープ分析。

3.古典的な言語に依存しない最適化手法の1つ:一般的な部分式の削除。

4.言語に関連する古典的な最適化手法の1つ:配列境界チェックの除去。

4、メソッドのインライン化

1.インライン化は、業界では最適化の母と呼ばれています。これは、メソッド呼び出しのコストを排除することに加えて、他の最適化メソッドの優れた基盤を確立することがより重要であるためです。

2.インライン化しないと、他のほとんどの最適化を効果的に実行できません。

3.メソッドのインライン化の最適化動作を理解すること、つまり、実際のメソッド呼び出しを回避するために、ターゲットメソッドのコードを呼び出しを開始したメソッドにそのまま「コピー」することは困難ではありません。

4.Javaメソッドが解析およびディスパッチされるとき

A:コンパイル時に解決されるのは、invokespecial命令を使用して呼び出される、invokestatic命令を使用して呼び出されるプライベートメソッド、インスタンスコンストラクター、親メソッド、および静的メソッドのみです。上記の4つのメソッドに加えて(最終的に変更されたメソッドの特殊なケースを削除しますが、invokevirtual命令を使用して呼び出されますが、非仮想メソッドでもあります。

B:Java言語のデフォルトのインスタンスメソッドは仮想メソッドです

5. Java仮想マシンは、仮想マシンの仮想メソッドのインライン問題をどのように解決しますか?

A:クラス階層分析(CHA)と呼ばれるテクノロジが導入されました。これは、アプリケーション全体の範囲内のタイプ分析テクノロジであり、現在ロードされているクラスでインターフェイスが使用可能かどうかを判断するために使用されます。複数の実装、特定のクラスにサブクラスがあるかどうか、特定のサブクラスが親クラスの特定の仮想メソッドをカバーするかどうかなど。

B:コンパイラがインライン化を実行する場合、状況に応じてさまざまな処理が行われます。非仮想メソッドの場合は、直接インライン化できます。この種のインライン化は100%安全です。検出された場合、仮想メソッド。CHAは、このメソッドに現在のプログラム状態で選択できる複数のターゲットバージョンがあるかどうかをクエリします。クエリにバージョンが1つしかない場合は、「アプリケーションの全体像が現在実行されているものである」と見なすことができます。インライン化を実行するために、この種のインライン化はGuardedInliningと呼ばれます。

C:Javaプログラムは動的に接続されているため、CHAの結論を変更するために新しいタイプにいつロードされるかは不確実です。したがって、この種のインライン化は根本的な予測最適化であり、「エスケープドア」を予約する必要があります。条件が満たされない場合の「スローパス」。その後のプログラムの実行時に、このメソッドの受信者の継承関係を変更するクラスに仮想マシンがロードされていない場合、このインライン最適化コードは永久に使用できます。継承関係の変更を引き起こす新しいクラスをロードする場合は、コンパイルされたコードを破棄するか、実行のために解釈された状態に戻るか、または再コンパイルする必要があります。

6.インラインバッファリング

A:インラインキャッシュは、ターゲットメソッドの通常のエントリの前に構築されたキャッシュです。その動作原理は、おおよそ次のとおりです。メソッド呼び出しが発生する前は、インラインキャッシュの状態は空です。最初の呼び出しが発生すると、キャッシュはメソッドを記録します。受信者のバージョン情報、およびメソッドが呼び出されるたびに受信者のバージョンを比較します。

B:各着信メソッドのレシーバーバージョンが同じである場合、それはモノモーフィックインラインキャッシュ(モノモーフィックインラインキャッシュ)です。このキャッシュを介して呼び出すには、インライン化されていない非仮想メソッド呼び出しを使用するよりも、タイプ決定のオーバーヘッドが1つ多く必要です。

C:メソッドレシーバーに本当に一貫性がない場合は、プログラムが仮想メソッドのポリモーフィック特性を使用していることを意味します。この時点で、メガモーフィックインラインキャッシュ(メガモーフィックインラインキャッシュ)に縮退し、そのコストは仮想メソッドを見つけるのと同じです。メソッドディスパッチのテーブル。

5、脱出分析

エスケープ分析は、現在のJava仮想マシンの最先端の最適化テクノロジーです。型継承分析と同様に、コードを直接最適化する手段ではなく、他の最適化手段の基礎を提供する分析テクノロジーです。

2.基本原則は次のとおりです。オブジェクトの動的スコープを分析します。オブジェクトがメソッドで定義されている場合、他のメソッドに呼び出しパラメーターとして渡されるなど、外部メソッドによって参照される場合があります。これはメソッドエスケープと呼ばれます。他のスレッドでアクセスできるインスタンス変数に値を割り当てるなど、外部スレッドからアクセスできます。これはスレッドエスケープと呼ばれます。エスケープしない、メソッドエスケープからスレッドエスケープへのメソッドエスケープは、オブジェクトエスケープの程度が低いものから高いものへと呼ばれます。

3.オブジェクトがメソッドまたはスレッドの外部にエスケープしない(つまり、他のメソッドまたはスレッドがオブジェクトにアクセスできない)ことが証明できる場合、またはエスケープの程度が比較的低い(メソッドからエスケープするだけでエスケープしない)場合。スレッド外)、このオブジェクトインスタンスに対してさまざまな程度の最適化を行うことができます

A:スタック割り当て[図](スタック割り当て):Java仮想マシンでは、オブジェクトを作成するためのメモリスペースがJavaヒープに割り当てられます。オブジェクトが保持されている限り、Javaヒープ内のオブジェクトは共有され、各スレッドに表示されます。参考までに、ヒープに格納されているオブジェクトデータにアクセスできます。仮想マシンのガベージコレクションサブシステムは、ヒープで使用されなくなったオブジェクトを再利用しますが、再利用アクションでは、リサイクル可能なオブジェクトをマークして除外する場合でも、メモリを再利用して配置する場合でも、多くのリソースが必要です。オブジェクトがスレッドから脱出しないと判断された場合は、このオブジェクトにスタック上のメモリを割り当てさせることをお勧めします。スタックフレームがポップされると、オブジェクトが占有していたメモリスペースが破壊される可能性があります。一般的なアプリケーションでは、まったくエスケープしないローカルオブジェクトとスレッドからエスケープしないローカルオブジェクトの割合が非常に大きく、スタック割り当てを使用できる場合は、メソッドの終了時に多数のオブジェクトが自動的に破棄されます。 、ガベージコレクションサブシステムへの圧力は大幅に低下します。スタックでの割り当てはメソッドエスケープをサポートできますが、スレッドエスケープはサポートできません

B:スカラー置換:データをより小さなデータに分解して表すことができなくなった場合、Java仮想マシンのプリミティブデータタイプ(int、long、参照タイプなどの数値タイプ)をさらに分解することはできません。 、これらのデータはスカラーと呼ぶことができます。対照的に、データの一部が引き続き分解できる場合、それは集約と呼ばれます。Javaのオブジェクトは典型的な集約です。Javaオブジェクトが逆アセンブルされ、その中で使用されているメンバー変数がプログラムのアクセスに応じてアクセスできるように元のタイプに復元される場合、このプロセスはスカラー置換と呼ばれます。エスケープ分析により、メソッドがオブジェクトにアクセスできず、オブジェクトを逆アセンブルできることが証明できる場合、プログラムは実際に実行されたときにオブジェクトを作成せず、このメソッドで使用されるメンバーのいくつかを直接作成する場合があります。代わりに変数。オブジェクトが分割された後、オブジェクトのメンバー変数をスタックに割り当てて読み書きできるようにすることに加えて(スタックに格納されたデータは、仮想マシンによって物理マシンの高速レジスタに割り当てられて格納される可能性があります)、その後の使用にも使用できます。さらなる最適化とは、条件を作成することを意味します。スカラー置換は、スタックでの割り当ての特殊なケースと見なすことができ、実装は簡単です(オブジェクト全体の完全な構造の割り当てを考慮しないでください)が、エスケープの程度の要件は高く、オブジェクトがメソッドのスコープからエスケープすることはできません。

C:同期の排除:スレッドの同期自体は比較的時間のかかるプロセスです。エスケープ分析で、変数がスレッドをエスケープせず、他のスレッドからアクセスできないと判断できる場合、この変数の読み取りと書き込みは絶対に行われません。この変数に実装されている競合、同期対策は安全に排除できます。

4.エスケープ分析の計算コストは​​非常に高く、エスケープ分析によってもたらされるパフォーマンス上の利点がその消費を超えるという保証すらありません。オブジェクトがエスケープするかどうかを100%の精度で判断する場合は、実行中にプログラムの各ブランチがオブジェクトに与える影響を判断するために、一連の複雑なデータフローセンシティブなプロシージャ間分析が必要です。

5.パラメータ-XX:+ DoEscapeAnalysisを使用して、エスケープ分析を手動でオンにすることができます。開いた後、パラメータ-XX:+ PrintEscapeAnalysisを使用して、分析結果を表示できます。エスケープ分析のサポートにより、ユーザーはパラメーター-XX:+ EliminateAllocationsを使用してスカラー置換をオンにし、+ XX:+ EliminateLocksを使用して同期除去をオンにし、パラメーター-XX:+ PrintEliminateAllocationsを使用してスカラー置換を表示できます。

6.エスケープ分析テクノロジーは、一連のより実用的で効果的な最適化テクノロジーを確実にサポートします。

6つの一般的なサブワード式の削除

1.一般的な部分式の削除は、さまざまなコンパイラで一般的に使用される非常に古典的な最適化手法です。その意味は次のとおりです。式Eが以前に計算された場合、および前の計算から現在のEまでのすべての変数の値は変更されていないため、このEの出現は共通部分式と呼ばれます。

2.この種の式の場合、再計算に時間を費やす必要はありません。Eを以前に計算された式の結果に直接置き換えるだけです。この種の最適化がプログラムの基本ブロックに限定されている場合は、ローカル共通部分式の削除と呼ぶことができます。この種の最適化の範囲が複数の基本ブロックをカバーしている場合は、グローバル共通部分式と呼ばれます。エリミネーション(グローバル共通サブエクスプレッションエリミネーション)。

7、配列境界チェックの除去

1. Array Bounds Checking Eliminationは、ジャストインタイムコンパイラにおける古典的な言語関連の最適化手法です。

Java言語で配列要素foo [i]にアクセスすると、システムは自動的に上限と下限をチェックします。つまり、「i> = 0 && i <foo.length」のアクセス条件を満たす必要があります。そうでない場合、ランタイム例外がスローされます。 :Java.lang.ArrayIndexOutOfBoundsException。これはソフトウェア開発者にとって非常に友好的なことです。プログラマーが特に防御的なコードを書かなくても、ほとんどのオーバーフロー攻撃を回避できます。ただし、仮想マシンの実行サブシステムの場合、配列要素の読み取りと書き込みが行われるたびに、暗黙の条件付き判定操作が行われます。配列アクセスの数が多いプログラムコードの場合、これはパフォーマンスである必要があります。重荷

2.オートボックスの消去、セーフポイントの消去、反射除去など。

おすすめ

転載: blog.csdn.net/qq_40996741/article/details/109153641