web-dev-qa-db-ja.com

JVMはどのようにしてメソッドをJITコンパイルする(メソッドを「ホット」として分類する)ことを決定しましたか?

私はすでに-XX:+PrintCompilation、私はJITコンパイラの基本的なテクニックと、JITコンパイルが使用される理由を知っています。

それでも、JVMがメソッドのJITコンパイルをどのように決定するか、つまり「適切なタイミングでメソッドがJITコンパイルされるようになったとき」はまだわかりません。

すべてのメソッドが解釈され始め、「ホットメソッド」として分類されない限り、コンパイルされないという前提で正しいのでしょうか。頭の後ろに、メソッドが少なくとも10.000回実行された場合(メソッドを10.000回解釈した後、コンパイルされる)、「ホット」と見なされると書いてありますが、私はそれを認めなければなりません。これについて、または私がこれを読んだ場所がわからない。

だから私の質問を要約すると:

(1)Is everyメソッドが「ホット」メソッドとして分類されていない(したがってコンパイルされている)限り解釈されるか、「ホット」メソッドでなくてもメソッドがコンパイルされる理由があるか「?

(2)JVMはメソッドを「非ホット」メソッドと「ホット」メソッドにどのように分類しますか?実行回数は?他に何か?

(3)「ホット」メソッドに特定のしきい値(実行数など)がある場合、Javaフラグ(-XX:...)このしきい値を設定するには?

31
Markus Weninger

HotSpotコンパイルポリシーは、特にJava 8でデフォルトでオンになっている階層化コンパイル)の場合、かなり複雑です。これは、実行回数ではなく、CompileThresholdパラメータの問題でもありません。

最良の説明(どうやら、唯一の合理的な説明)はHotSpotソースで見つけることができます advancedThresholdPolicy.hpp を参照してください。

この高度なコンパイルポリシーの主なポイントを要約します。

  • 実行はTier 0(インタープリター)から開始されます。
  • コンパイルの主なトリガーはです。
    1. メソッド呼び出しカウンターi;
    2. バックエッジカウンターb。後方分岐は通常、コード内のループを示します。
  • カウンターが特定の頻度値(TierXInvokeNotifyFreqLogTierXBackedgeNotifyFreqLog)に達するたびに、現在実行中のメソッドで次に何を行うかを決定するために、コンパイルポリシーが呼び出されます。 ibの値、およびC1およびC2コンパイラスレッドの現在の負荷に応じて、次のように決定できます。

    • インタプリタで実行を継続します。
    • インタプリタでプロファイリングを開始します。
    • さらに再コンパイルするために必要な完全なプロファイルデータを使用して、層3でC1を使用してメソッドをコンパイルします。
    • ティア2でC1を使用してメソッドをコンパイルします。プロファイルはありませんが、再コンパイルする可能性があります(可能性は低い)。
    • 最後に、プロファイルもカウンターもない(同様にありそうもない)、Tier 1のC1でメソッドをコンパイルします。

    ここで重要なパラメータはTierXInvocationThresholdTierXBackEdgeThresholdです。コンパイルキューの長さに応じて、特定のメソッドのしきい値を動的に調整できます。

  • コンパイルキューはFIFOではなく、優先キューです。

  • プロファイルデータ(層3)を含むC1でコンパイルされたコードも同様に動作しますが、次のレベル(C2、層4)に切り替えるためのしきい値がはるかに大きくなります。例えば。インタプリタされたメソッドは、約200回の呼び出し後にティア3でコンパイルできますが、C1でコンパイルされたメソッドは、5000回以上の呼び出し後にティア4で再コンパイルされます。

  • メソッドのインライン化には特別なポリシーが使用されます。小さなメソッドは、「ホット」でなくても呼び出し元にインライン化できます。少し大きいメソッドは、頻繁に呼び出される場合にのみインライン化できます(InlineFrequencyRatioInlineFrequencyCount)。
55
apangin

これを制御する主なパラメータは-XX:CompileThreshold=10000

Java= 8のホットスポットは、レベル1から4までのコンパイルの段階数を使用して、デフォルトで段階的コンパイルを使用するようになりました。1は最適化されていないと思います。レベル3はC1(クライアントクライアントに基づく) )、レベル4はC2(サーバーコンパイラに基づく)

つまり、予想よりも少し早く最適化が行われる可能性があり、10Kのしきい値に達した後もずっと最適化を続けることができます。私が見た最高のものは、100万回の呼び出し後にStringBuilderを排除するエスケープ分析です。

注:ループを何度も繰り返すと、コンパイラーがトリガーされます。例えば10K回のループで十分です。

1)メソッドが十分にホットであると見なされるまで、解釈されます。ただし、一部のJVM(Azul Zingなど)は起動時にメソッドをコンパイルでき、Hotspot JVMに内部APIを介してメソッドを強制的にコンパイルさせることができます。 Java 9にはAOT(Ahead Of Time)コンパイラも搭載されている可能性がありますが、まだ調査中です。

2)呼び出しの数、または反復の数。

3)はい-XX:CompileThreshold=がメインです。

9
Peter Lawrey