java jvm jit jvm-hotspot

java - ¿Cómo decidió la JVM compilar JIT un método(categorizar un método como "activo")?



jvm-hotspot (2)

Ya trabajé con -XX:+PrintCompilation , y conozco las técnicas básicas del compilador JIT y por qué se utiliza la compilación JIT.

Sin embargo, todavía no he descubierto cómo la JVM decide compilar un método JIT, es decir, "cuando ha llegado el momento adecuado de compilar un método JIT".

¿Estoy en lo cierto en el supuesto de que cada método comienza a ser interpretado, y mientras no se clasifique como "método activo" no se compilará? Tengo algo en la parte posterior de mi cabeza que leí que un método se considera "activo" cuando se ejecutó al menos 10.000 veces (después de interpretar el método 10.000 veces, se compilará), pero tengo que admitir que estoy No estoy seguro de esto o de dónde he leído esto.

Para resumir mi pregunta:

(1) ¿Se interpreta cada método siempre que no se haya categorizado como método "activo" (y, por lo tanto, se haya compilado) o hay razones para que los métodos se compilen incluso si no están "activos"?

(2) ¿Cómo clasifica la JVM los métodos en métodos "no activos" y "activos"? Número de ejecuciones? ¿Algo más?

(3) Si hay ciertos umbrales (como el número de ejecuciones) para los métodos " -XX:... ", ¿hay indicadores Java ( -XX:... ) para establecer estos umbrales?


El parámetro principal para controlar esto es -XX:CompileThreshold=10000

Hotspot para Java 8 ahora usa una compilación escalonada de forma predeterminada utilizando una serie de etapas de compilación del nivel 1 al 4. Creo que 1 no es una optimización. El nivel 3 es C1 (basado en el cliente cliente) y el nivel 4 es C2 (basado en el compilador del servidor)

Esto significa que una pequeña optimización puede suceder antes de lo esperado y puede seguir optimizando mucho después de que haya alcanzado el umbral de 10K. Lo más alto que he visto es el análisis de escape que elimina un StringBuilder después de un millón de llamadas.

Nota: un bucle que se repite muchas veces puede activar el compilador. Por ejemplo, un bucle de 10K veces puede ser suficiente.

1) Hasta que un método se considere suficientemente activo, se interpretará. Sin embargo, algunas JVM (por ejemplo, Azul Zing) pueden compilar métodos al inicio y puede forzar a la JVM de Hotspot a compilar un método a través de una API interna. Java 9 también puede tener un compilador AOT (Ahead Of Time) pero aún se está investigando AFAIK

2) Número de llamadas o número de iteraciones.

3) Sí -XX:CompileThreshold= siendo el principal.


La política de compilación de HotSpot es bastante compleja, especialmente para la compilación escalonada, que está CompileThreshold por defecto en Java 8. No es una serie de ejecuciones ni una cuestión de parámetro CompileThreshold .

La mejor explicación (aparentemente, la única explicación razonable) se puede encontrar en las fuentes de HotSpot, consulte advancedThresholdPolicy.hpp .

Resumiré los puntos principales de esta política de compilación avanzada:

  • La ejecución comienza en el nivel 0 (intérprete).
  • Los principales desencadenantes para la compilación son
    1. contador de invocación de método i ;
    2. contador de respaldo b . Las ramas hacia atrás generalmente denotan un bucle en el código.
  • Cada vez que los contadores alcanzan cierto valor de frecuencia ( TierXInvokeNotifyFreqLog , TierXBackedgeNotifyFreqLog ), se llama a una política de compilación para decidir qué hacer a continuación con el método actualmente en ejecución. Dependiendo de los valores de i , b la carga actual de los subprocesos del compilador C1 y C2, se puede decidir

    • continuar ejecución en intérprete;
    • comenzar a perfilar en intérprete;
    • compile el método con C1 en el nivel 3 con los datos de perfil completos necesarios para una nueva compilación;
    • método de compilación con C1 en el nivel 2 sin perfil pero con posibilidad de recompilar (poco probable);
    • finalmente compile el método con C1 en el nivel 1 sin perfil ni contadores (también poco probable).

    Los parámetros clave aquí son TierXInvocationThreshold y TierXBackEdgeThreshold . Los umbrales se pueden ajustar dinámicamente para un método determinado dependiendo de la longitud de la cola de compilación.

  • La cola de compilación no es FIFO, sino más bien una cola prioritaria.

  • El código compilado con C1 con datos de perfil (nivel 3) se comporta de manera similar, excepto que los umbrales para cambiar al siguiente nivel (C2, nivel 4) son mucho más grandes. Por ejemplo, un método interpretado se puede compilar en el nivel 3 después de aproximadamente 200 invocaciones, mientras que el método compilado en C1 está sujeto a la compilación en el nivel 4 después de más de 5000 invocaciones.

  • Se utiliza una política especial para la incorporación de métodos. Se pueden insertar pequeños métodos en la persona que llama, incluso si no están "calientes". Los métodos un poco más grandes se pueden insertar solo si se invocan con frecuencia ( InlineFrequencyRatio , InlineFrequencyCount ).