JIT ジャストインタイム コンパイラ

1. インタプリタとコンパイラ

Javaプログラムは実行時に主にバイトコード命令を実行しますが、一般的にはこれらの命令をインタプリタ(Interpreter)が解釈して実行することをインタープリタ実行といいます。

仮想マシンは、特定のメソッドまたはコード ブロックが特に頻繁に実行されることを検出すると、これらのコードをホット コードとして識別しますホットコードの実行効率を向上させるために、仮想マシンは実行時にホットコードをローカルプラットフォームに関連するマシンコードにコンパイルし、さまざまなレベルの最適化を実行します。このタスクを完了するコンパイラはジャストインタイムと呼ばれます。コンパイラ (Just In Time Compiler、JIT コンパイラと呼ばれます)。
ここに画像の説明を挿入
HotSpot 仮想マシンには、クライアント コンパイラとサーバー コンパイラ、または略して C1 コンパイラと C2 コンパイラと呼ばれる 2 つのジャストインタイム コンパイラが組み込まれています。

  • C1 コンパイラー
    シンプルで高速なコンパイラー。主にローカル最適化に重点が置かれており、実行時間が短いプログラムや起動パフォーマンスの要件があるプログラムに適しています。開始時間が早くなり、C1 はアプリケーションの開始直後にコンパイルを開始します。

  • C2 コンパイラは、
    長時間実行されるサーバー側アプリケーションのパフォーマンス チューニング用のコンパイラで、実行時間が長いプログラムやピーク パフォーマンス要件があるプログラムに適しています。実行時間が遅く、プログラムが一定時間実行された後にコンパイルが開始されます


使用するコンパイラが C1 か C2 かに関係なく、仮想マシンではインタプリタとコンパイルの組み合わせを「混合モード」と呼びます。
ここに画像の説明を挿入
パラメータを使用して-Xint仮想マシンを強制的に「インタープリタ モード」で実行できます。このモードでは、コンパイラはまったく機能せず、すべてのコードが解釈を使用して実行されます。

-Xcompパラメータを使用して、仮想マシンを「コンパイラ モード」で強制的に実行することもできます。このとき、プログラムの実行にはコンパイル モードが優先されますが、コンパイルを実行できない場合は、インタープリタが実行プロセスに介入する必要があります


2. ホットコードとホットスポットの検出

ホット コードとは、頻繁に呼び出されるコードのことで、次回使用するためにコンパイルされてキャッシュされますが、めったに実行されないコードの場合、このコンパイル アクションはまったく無駄です。


JVM には CodeCache のサイズを制限するパラメータが用意されており-XX:ReservedCodeCacheSize、JIT によってコンパイルされたコードは CodeCache に配置されます。JDK7のデフォルト値は32m~48m、JDK8のデフォルト値は240mです。

スペースが不足すると、JIT はコンパイルを続行できず、コンパイル実行がインタープリタ実行となり、パフォーマンスが低下します。同時に、JIT コンパイラーは常にコードの最適化を試みるため、CPU 使用率が増加します。


コードがホット コードであるかどうか、またはすぐにコンパイルする必要があるかどうかを判断することをホット スポット検出といいます。ホット スポットの検出方法には主に次の 2 つがあります。

  1. サンプリング ベースのホットスポット検出:このメソッドを使用する仮想マシンは、各スレッドのスタック トップを定期的にチェックし、特定の (または一部の) メソッドがスタックのトップに頻繁に現れることが判明した場合、そのメソッドは「ホット メソッド」です。 」。

    短所: サンプリングベースのホットスポット検出の利点は、実装が簡単で効率的であること、メソッドの呼び出し関係を取得するのも簡単であること (コール スタックを展開するだけ)、欠点は、正確な確認が難しいことです。メソッドの熱が高く、スレッドによってブロックされやすい、または他の外部要因の影響によりホットスポットの検出が妨げられます。

  2. カウンタベースのホットスポット検出:このメソッドを使用する仮想マシンは、各メソッド (コード ブロックも含む) にカウンタを作成し、メソッドの実行数をカウントし、実行数が一定を超えた場合にそのメソッドを「ホット メソッド」と見なします。しきい値。

    短所: この統計手法は実装が面倒で、メソッドごとにカウンタを確立して維持する必要があり、メソッドの呼び出し関係を直接取得できませんが、統計結果は比較的正確で厳密です。


HotSpot 仮想マシンは、2 番目のタイプであるカウンターベースのホットスポット検出に基づいており、メソッドごとに 2 種類のカウンター (メソッド呼び出しカウンターとエッジ戻りカウンター) を用意します。

2.1、メソッド呼び出しカウンター

これは、メソッドが呼び出された回数をカウントするために使用されます。デフォルトのしきい値は、クライアント モードでは 1500 回、サーバー モードでは 10000 回です。このしきい値は、仮想マシン パラメータを通じて人為的に設定できます-XX:CompileThreshold

メソッドが呼び出されるとき、メソッドの JIT コンパイル バージョンがあるかどうかが最初にチェックされます。存在する場合は、コンパイルされたネイティブ コードが最初に使用されます。コンパイルされたバージョンがない場合、メソッドが呼び出されます。カウンタは次のとおりです。メソッド呼び出しカウンタとリターン呼び出しカウンタの合計がメソッド呼び出しカウンタのしきい値を超えているかどうかを判定し、しきい値を超えている場合はメソッドのコードコンパイル要求をメソッド呼び出しカウンタに送信します。 -in-time コンパイラ。


設定を行わない場合、メソッド呼び出しカウンタはメソッドの絶対的な呼び出し回数ではなく、相対的な実行頻度、および一定時間内にメソッドが呼び出された回数をカウントします。特定の制限時間を超えたとき、メソッドの呼び出し数がコンパイルのためにジャストインタイム コンパイラに送信するにはまだ十分ではない場合、このメソッドの呼び出しカウンターは半分に減らされます。このプロセスが呼び出されます。メソッドコールのカウンターヒートの減衰。

前述のメソッド呼び出しカウンターの熱を軽減するために、仮想マシンのパラメーターを使用して熱の減衰をオフにすることもできます。-XX:-UseCounterDecayメソッド カウンターにメソッド呼び出しの絶対数をカウントさせることで、システムが十分に長く実行される限り、ほとんどののコードがコンパイルされます。 コンパイラーはネイティブ コードをコンパイルします。さらに、-XX:CounterHalfLifeTimeパラメータを使用して半減期サイクルの時間を秒単位で設定することもできます。


2.2. エッジリターンカウンタ

メソッド内のループ本体のコードが実行された回数をカウントする機能で、バイトコードでは制御フローが逆方向にジャンプする命令を「バックエッジ」と呼びます。メソッド呼び出しカウンタとは異なり、戻りエッジ カウンタは熱減衰プロセスをカウントしないため、このカウンタはループ内でメソッドが実行された絶対回数をカウントします。


3、レイヤードコンピレーション

前述の C1 および C2 コンパイラの長所と短所に基づいて、仮想マシンは通常、階層化コンパイルの戦略を開始します (階層化コンパイル パラメータを有効にします)。階層化コンパイルは、コンパイラのコンパイルの規模と時間に基づいており-XX:+TieredCompilation、最適化では、次のようなさまざまなコンパイル レベルが分割されます。

  1. レイヤ 0 では、プログラムが解釈されて実行され、インタプリタがパフォーマンス監視機能を開始します。これにより、レイヤ 1 のコンパイルが開始されます。
  2. 最初の層は C1 コンパイルとも呼ばれ、バイトコードをネイティブ コードにコンパイルし、シンプルで信頼性の高い最適化を実行し、必要に応じてパフォーマンス監視ロジックを追加します。
  3. C2 コンパイルとも呼ばれるレイヤー 2 も、バイトコードをネイティブ コードにコンパイルしますが、コンパイルに時間がかかるいくつかの最適化を開始し、パフォーマンス監視情報に基づいて信頼性の低い積極的な最適化を実行することもあります。

階層化コンパイルが実装されると、C1 と C2 が同時に動作し、多くのコードが複数回コンパイルされる可能性があります。より高いコンパイル速度を得るには C1 コンパイラを使用し、より高いコンパイル品質を得るには C2 コンパイラを使用します。


4番目、コンパイルの最適化

4.1. メソッドのインライン化

メソッドのインライン化の最適化動作は、実際のメソッド呼び出しを回避するために、ターゲット メソッドのコードを呼び出し側メソッドにコピーすることです。
ここに画像の説明を挿入
JVM はホット メソッドを自動的に認識し、メソッド インライン化を使用してそれらを最適化します。ただし、ホットスポット メソッドは JVM によってインライン化されない場合があります。たとえば、メソッド本体が大きすぎる場合、JVM はインライン操作を実行しません。デフォルトでは、本体が 325 バイト未満のメソッドはインライン化されます。サイズ値-XX:FreqInlineSize=Nは による。


4.2. スカラー置換

エスケープ解析により、オブジェクトが外部からアクセスされないことが証明されており、オブジェクトが分割できる場合には、実際のプログラム実行時にオブジェクトが作成されず、そのメンバ変数が直接作成される可能性があります。
ここに画像の説明を挿入
オブジェクトを分割した後、オブジェクトのメンバー変数をスタックまたはレジスタに割り当てることができ、元のオブジェクトにメモリ領域を割り当てる必要はありません。この種のコンパイルの最適化は、スカラー置換と呼ばれます (エスケープ分析をオンにする必要がある場合)。

おすすめ

転載: blog.csdn.net/rockvine/article/details/124864757
おすすめ