Javaのインスタントコンパイル

4020 ワード

階層型コンパイルモード
HotSpot仮想マシンは、複数のインスタントコンパイラC 1、C 2を含む
C1
  • のコンパイル効率が速く、パラメータ-clientに対応し、実行時間が短い、または起動性能に要求されるプログラム
  • に対して.
  • は、プログラムができるだけ早くコンパイル実行段階に入ることを目的としているため、収集が多くないため、コンパイル速度が速い
  • である.
    C2
  • 生成コードの実行効率が速く、パラメータ-serverに対応し、実行時間が長く、ピーク性能に要求されるプログラムである.
  • 機械コードにコンパイルする場合、コンパイル時に最適化するために大量の統計情報を収集する必要があるため、コンパイルされたコードの実行効率は
  • より速い.
    Java 7は階層コンパイル(対応パラメータ-XX:+TieredCompilation)を導入し、C 1の起動性能の優位性とC 2のピーク性能の優位性を統合した.
    階層型コンパイルでは、Java仮想マシンの実行ステータスを5つの階層に分けます.
  • 解析実行
  • profilingを持たないC 1コード
  • を実行する.
  • メソッド呼び出し回数およびループバック実行回数profillingのみを持つC 1コード
  • を実行する.
  • は、全てのprofilingを有するC 1コード
  • を実行する.
  • は、C 2コード
  • を実行する.
    profilingとは、プログラム実行中にプログラム実行状態を反映できるデータを収集することを指す.Profileはランタイム状態情報を収集し,コンパイラ最適化に用いるが,もちろん情報収集も性能を消費するため,最適化の可能性がある場合には関連情報の収集に苦労する前提条件もある.
    1.8はデフォルトで階層化コンパイルをオンにし、Java仮想マシンをオフにすると直接C 2を選択する
    インスタントコンパイルのトリガ
    Java仮想マシンは,メソッドの呼び出し回数およびループバックエッジ(ジャンプバック命令)の実行回数に基づいてインスタントコンパイルをトリガし,Java仮想マシンは0,2,3層の実行状態でprofilingを行い,メソッドの呼び出し回数とループバックエッジの実行回数を含む.
    public static void foo(Object obj) {
      int sum = 0;
      for (int i = 0; i < 200; i++) {
        sum += i;
      }
    }
    

    上記のコードは、次のバイトコードにコンパイルされます.ここで、オフセット量18のバイトコードは、オフセット量7のバイトコードに戻る.解釈実行時には,この命令を1回実行するたびにJava仮想マシンはメソッドのループバックカウンタに1を加算する.
    public static void foo(java.lang.Object);
      Code:
         0: iconst_0
         1: istore_1
         2: iconst_0
         3: istore_2
         4: goto 14
         7: iload_1
         8: iload_2
         9: iadd
        10: istore_1
        11: iinc 2, 1
        14: iload_2
        15: sipush 200
        18: if_icmplt 7
        21: return
    

    インスタントコンパイルプロセスでは、ループのヘッダとテールを識別します.上のコードでは、ループのヘッダはオフセット量14のバイトコードであり、テールはオフセット量11のバイトコードであり、それらの制御フローエッジはループバックエッジであり、つまりC 1はこの位置にループバックカウンタを追加するコードを挿入します.
    階層コンパイルを開始しない場合、メソッドの呼び出し回数とループバック回数の和が、パラメータXX:CompileThresholdで指定されたしきい値を超えると(C 1:値が1500、C 2:値が10000)、インスタントコンパイルがトリガーされます.
    階層コンパイルが開始されると、しきい値のサイズは動的に調整されます.
    しきい値を比較すると、Java仮想機会はしきい値を係数sに乗算します.この係数は、現在コンパイルされる方法の数と正に相関し、コンパイルスレッドの数と負に相関する.
    OSRコンパイル
    1つのメソッドがホットスポットコードであるかどうかを決定する要因は2つあります.
  • メソッドの呼び出し回数
  • ループバックエッジの実行回数
  • インスタントコンパイルは、この2つのカウンタの和に基づいてトリガーされます.
    メソッド単位のインスタントコンパイルに加えて、Java仮想マシンにはOn-stack-REplacement(OSR)コンパイルというサイクル単位のインスタントコンパイルが存在する.ループバックカウンタは、このタイプのコンパイルをトリガするために使用されます.
    OSRは実際には、プログラム実行中にJavaメソッドスタックフレームを動的に置き換え、プログラムが非メソッド入口で解釈実行とコンパイル後のコード間の切り替えを行うことができ、最適化(実行マシンコードから解釈実行に切り替える)に用いる技術をOSRと呼ぶこともできる.OSRコンパイルは、単一の呼び出し方法が熱サイクルを含む性能最適化の問題を解決するために使用することができる.
    OSRコンパイルは通常のアプリケーションではあまり見られません.ベンチマークテストでのみ一般的です.
    まとめ
  • Java 8から、Java仮想マシンはデフォルトで階層的にコンパイルされます.それは実行を5つの階層に分けて、0層解釈実行に分けて、1層はprofilingのないC 1コードを実行して、2層は部分profilingのC 1コードを実行して、3層はすべてprofilingのC 1コードを実行して、4層はC 2コードを実行します.
  • 通常、方法は、まず解釈されて実行され、次いで3層のC 1によってコンパイルされ、最後に4層のC 2によってコンパイルされる.
  • インスタントコンパイルは、メソッド呼び出しカウンタとループバックカウンタによってトリガーされる.階層型コンパイルを使用する場合、コンパイルをトリガするしきい値は、現在コンパイルされる方法の数に応じて動的に調整される.
  • OSRは、非方法の入口で解釈実行とコンパイル後のコード間の切り替えを行うことができる技術である.OSRコンパイルは、単一の呼び出し方法が熱サイクルを含む性能最適化問題
  • を解決するために使用することができる.