2012-04-13 8 views
8

He leído y oído mucho acerca de cómo los compiladores JIT pueden hacer optimizaciones que son imposibles para los compiladores de código nativo y que estas optimizaciones pueden dar un gran impulso al rendimiento.Optimizaciones JIT en su máxima expresión

Me preguntaba, ¿cuáles son las optimizaciones más importantes que, por ejemplo, el .NET Framework o la JVM hacen que un compilador nativo no puede hacer? Además, ¿cómo estos dan aumentos de rendimiento enorme?

No sé si he formulé esta pregunta correctamente, supongo que puede tener mucho que explicar en los comentarios

+0

@TimMedora: El enlace parece referirse a las optimizaciones realizadas por el compilador de C-ahead-time, no el compilador de CLR just-in-time. –

Respuesta

4

puedo dar un ejemplo de una optimización. Supongamos que tiene una función en alguna parte. (Piense en esto como un pseudocódigo tipo C.)

void function(MyClass x) 
{ 
    x.doSomething(); 
    for (obj in x.getWidgets()) 
     obj.doSomethingElse(); 
} 

Esto es bastante vago. Supongamos, sin embargo, que solo tiene una clase concreta en toda su imagen que hereda de MyClass: MyConcreteClass. En ese caso, el JIT puede en línea doSomething y getWidgets. Si sabe sobre el tipo devuelto desde getWidgets, entonces tal vez puede alinear doSomethingElse también.

Suponiendo que MyClass no es una clase final/sellada, un compilador adelantado no puede alinear su método (no sabría qué funciones alinear); para todo lo que sabe el compilador, hay cientos de implementaciones diferentes de MyClass.

Sin embargo, un JIT se puede optimizar para el estado actual de la imagen . Puede instalar un cheque al comienzo de cada llamada al function que se asegura de que x es un MyConcreteClass, y luego ejecuta la versión impresa. Si dinámicamente carga un módulo con otra clase concreta que hereda de MyClass, la verificación fallará y el JIT recompilará la función para que sea genérica.

Estos son los únicos tipos de optimizaciones disponibles para los compiladores JIT que no están disponibles a por delante de los tiempos compiladores: optimizaciones que hacen uso de la información sobre el estado dinámico del programa y volver a compilar el programa en consecuencia.

Tenga en cuenta que algunos compiladores anticipados son capaces de hacer trucos típicamente atribuidos a los compiladores JIT. Por ejemplo, optimización interprocedural (o optimización global) y optimización basada en perfiles. GCC y Clang pueden usar ambos trucos, pero la mayoría de las personas los descarta, ya que requiere un trabajo extra (humano) para activarlos. Los compiladores JIT pueden dejar esas opciones habilitadas sin molestar a los usuarios finales.

enorme aumento de rendimiento: No he oído hablar de ningún gran impulso en el rendimiento en general de los compiladores JIT. Los programas C y C++ aún son rápidos sin JIT. Y muchas personas todavía prefieren Fortran para el trabajo numérico (con buenas razones).

Nota al pie: No estoy seguro de su terminología. ¿No son la mayoría de los JIT también compiladores de códigos nativos? Los otros tipos de compiladores además de JIT I llamarían "antes de tiempo" o AOT, o quizás "estático". (Y luego está la línea increíblemente difusa entre "compilado" e "interpretado").

+0

-1 para "Estos son los únicos tipos de optimizaciones ..." JIT Los compiladores utilizan la optimización guiada de perfil para mejorar el rendimiento de callsite en rutas de programas calientes. (Tanto el MSFT CLR como el Hotspot hacen esto). Ese no es el "estado" del programa sino la dinámica del programa. Los compiladores JIT pueden usar información sobre la máquina en la que se ejecutan para guiar la optimización. El MSFT CLR hace esto, y Hotspot lo hace. Eso no tiene nada que ver con el programa. Los compiladores JIT también pueden usar información * state * de la máquina en la que se ejecutan para guiar la optimización. –

+0

No sé si las VM actuales lo hacen por última vez, pero es ciertamente posible. –

+0

@MichaelGraczyk: La razón por la que dije "este es el único tipo de optimizaciones" es porque las optimizaciones que menciona pueden ser, y de hecho lo son, compatibles con compiladores que no son JIT. GCC * * realizará una optimización basada en perfiles. La pregunta es solo acerca de las optimizaciones que los compiladores anticipados no pueden hacer. –

1

Javascript es un ejemplo mucho mejor, ya que no es tan amigable con los compiladores como la JVM o la CLR.

Los compiladores JIT pueden generar representaciones específicas de hormigón para las clases Javascript, lo cual es difícil para los compiladores estáticos ya que las clases pueden modificarse en cualquier momento durante la ejecución del programa. También puede alinear especulativamente las funciones llamadas en función de los tipos reales (Dietrich Epp ya lo explicó en su respuesta).

Los videos en http://code.google.com/p/v8/ explican bien esas optimizaciones.