¿Qué hace un compilador just-in-time (JIT)?

Respuestas:

518

Un compilador JIT se ejecuta después de que el programa ha comenzado y compila el código (generalmente código de bytes o algún tipo de instrucciones de VM) sobre la marcha (o justo a tiempo, como se llama) en una forma que generalmente es más rápida, generalmente la CPU nativa del host conjunto de instrucciones. Un JIT tiene acceso a información dinámica de tiempo de ejecución, mientras que un compilador estándar no tiene y puede hacer mejores optimizaciones, como funciones de línea que se usan con frecuencia.

Esto contrasta con un compilador tradicional que compila todo el código en lenguaje máquina antes de que el programa se ejecute por primera vez.

Parafraseando, los compiladores convencionales compilan todo el programa como un archivo EXE ANTES de la primera vez que lo ejecutas. Para los programas de estilo más nuevos, se genera un ensamblado con pseudocódigo (código p). Solo DESPUÉS de ejecutar el programa en el sistema operativo (por ejemplo, haciendo doble clic en su icono) el compilador (JIT) se activará y generará el código de máquina (código m) que el procesador basado en Intel o lo que sea que comprenda.

Mark Cidade
fuente
16
Y en contraste con el código interpretado, eso comienza a ejecutar el bytecode o las instrucciones de VM inmediatamente sin demora, pero ejecutará las instrucciones más lentamente que el lenguaje de máquina.
Aaron
3
Un JIT a menudo se usa con código interpretado para convertirlo a lenguaje de máquina, pero sí, el código puramente interpretado (sin JITting) es lento. Incluso el código de bytes de Java sin un JITter es realmente lento.
Mark Cidade
48
Sin embargo, el objetivo no tiene que ser el código de máquina. JRuby tiene un compilador JIT que compilará el código fuente de Ruby al código de bytes de Java después de un par de invocaciones. Luego, después de otro par de invocaciones, el compilador JVM JIT se activa y compila el código de bytes en código nativo.
Jörg W Mittag
44
Vale la pena señalar que, como lo aludió Jörg, JIT no se invoca necesariamente de inmediato. A menudo, el código se interpretará hasta que se determine que valdrá la pena JITAR. Dado que JITting puede introducir demoras, puede ser más rápido NO JITAR algún código si rara vez se usa y, por lo tanto, una respuesta rápida es más importante que el tiempo de ejecución general.
Adam Jaskiewicz
3
@ErikReppen: si sale una nueva máquina, compilar y optimizar un programa para esa nueva máquina usando un compilador convencional probablemente arroje resultados más rápidos que un JIT. Por otro lado, un JIT que esté optimizado para esa nueva máquina podrá optimizar el rendimiento del código que se publicó antes de que se inventara esa nueva máquina .
supercat
255

Al principio, un compilador era responsable de convertir un lenguaje de alto nivel (definido como un nivel superior al ensamblador) en código de objeto (instrucciones de máquina), que luego se vincularía (mediante un vinculador) en un ejecutable.

En un momento de la evolución de los lenguajes, los compiladores compilarían un lenguaje de alto nivel en pseudocódigo, que luego sería interpretado (por un intérprete) para ejecutar su programa. Esto eliminó el código objeto y los ejecutables, y permitió que estos lenguajes fueran portables a múltiples sistemas operativos y plataformas de hardware. Pascal (que compiló el código P) fue uno de los primeros; Java y C # son ejemplos más recientes. Finalmente, el término P-Code fue reemplazado por bytecode, ya que la mayoría de las pseudo-operaciones son de un byte largo.

Un compilador Just-In-Time (JIT) es una característica del intérprete en tiempo de ejecución, que en lugar de interpretar el código de bytes cada vez que se invoca un método, compilará el código de bytes en las instrucciones del código de máquina de la máquina en ejecución, y luego invocará esto código objeto en su lugar. Idealmente, la eficiencia de ejecutar código objeto superará la ineficiencia de recompilar el programa cada vez que se ejecuta.

Craig Trader
fuente
55
Sin embargo, esta frase "un compilador Just-In-Time (JIT) es una característica del intérprete en tiempo de ejecución" causa confusión; por ejemplo: stackoverflow.com/questions/16439512/…
Stephen C
11
En realidad, el JIT era un complemento, y aún puede deshabilitarlo usando el parámetro -Xint para Java, por lo que es solo una característica.
Craig Trader
3
No estoy totalmente de acuerdo. JIT no es evolución, es una alternativa a los compiladores clásicos.
i486
1
JIT es un paso en el camino evolutivo desde los interruptores mecánicos de cableado duro hasta la especificación de criterios de búsqueda diciendo "OK Google" a su teléfono inteligente. El JIT actual disponible como parte de Java 7/8 está a pasos agigantados más allá de lo que estaba disponible como parte de Java 2, eso también es evolución.
Craig Trader
1
@ i486 - Sun / Oracle (AFAIK) nunca envió un compilador clásico ("por adelantado") para Java que genera código nativo. Es difícil argumentar que JIT es una alternativa ... cuando creen que es supuestamente una alternativa, nunca se envió. (Descarto el compilador GCJ AOT porque eso no tenía nada que ver con Sun / Oracle, y tampoco era una solución completa. Ciertamente, ahora no es viable.)
Stephen C
69

JIT: justo a tiempo, la palabra misma dice cuándo es necesario (bajo demanda)

Escenario típico:

El código fuente se convierte completamente en código de máquina.

Escenario JIT:

El código fuente se convertirá en lenguaje ensamblador como estructura [para ex IL (lenguaje intermedio) para C #, ByteCode para java].

El código intermedio se convierte en lenguaje de máquina solo cuando la aplicación necesita que los códigos requeridos solo se conviertan en código de máquina.

Comparación JIT vs no JIT:

  • En JIT, no todo el código se convierte en código de máquina primero, una parte del código que es necesario se convertirá en código de máquina y luego, si un método o funcionalidad llamada no está en la máquina, se convertirá en código de máquina ... se reduce carga en la CPU.

  • Como el código de máquina se generará en tiempo de ejecución ... el compilador JIT producirá código de máquina que está optimizado para ejecutar la arquitectura de CPU de la máquina.

Ejemplos JIT:

  1. En Java, JIT está en JVM (Java Virtual Machine)
  2. En C # está en CLR (Common Language Runtime)
  3. En Android está en DVM (Dalvik Virtual Machine), o ART (Android RunTime) en versiones más recientes.
Durai Amuthan.H
fuente
77
JIT ofrece algunas ventajas especiales en marcos con soporte para tipos genéricos reales; es posible definir un método genérico que sea capaz de producir un rango ilimitado de tipos, cada uno de ellos requeriría un código de máquina diferente, pero solo tiene el código JIT para generar los tipos que realmente se producen. Por el contrario, en C ++ es necesario que el compilador genere código para todos los tipos que utilizará un programa.
supercat
66
JVM no codifica JIT la primera vez que lo ejecuta. Las primeras veces, interpreta bytecode. Luego, si ese código se ejecuta con la frecuencia suficiente, puede decidir molestarse en JITARlo.
ninjalj
1
Estás diciendo que JIT en Java es JVM. Sin embargo, ya proporcionamos el código compilado a JVM, ¿no? Entonces lo compila de nuevo, ¿quieres decir?
Koray Tugay
@KorayTugay - Proporcionamos Bytecodes a JVM y JVM convertirá parte de eso a código de máquina a pedido, por lo que se ahorran recursos.
Durai Amuthan. H
1
En Java, JIT no es JVM. Es solo una parte de eso.
sucede
25

Como otros han mencionado

JIT significa Just-in-Time, lo que significa que el código se compila cuando es necesario, no antes del tiempo de ejecución.

Solo para agregar un punto a la discusión anterior, JVM mantiene un recuento de cuántas veces se ejecuta una función. Si este recuento excede un límite predefinido, JIT compila el código en lenguaje máquina que puede ser ejecutado directamente por el procesador (a diferencia del caso normal en el que javac compila el código en bytecode y luego java - el intérprete interpreta este bytecode línea por línea lo convierte en código de máquina y se ejecuta).

Además, la próxima vez que se calcule esta función, se ejecutará nuevamente el mismo código compilado, a diferencia de la interpretación normal en la que el código se interpreta nuevamente línea por línea. Esto hace que la ejecución sea más rápida.

Aniket Thakur
fuente
14

El compilador JIT solo compila el código de bytes a un código nativo equivalente en la primera ejecución. En cada ejecución sucesiva, la JVM simplemente usa el código nativo ya compilado para optimizar el rendimiento.

ingrese la descripción de la imagen aquí

Sin el compilador JIT, el intérprete JVM traduce el código de byte línea por línea para que parezca que se está ejecutando una aplicación nativa.

ingrese la descripción de la imagen aquí

Fuente


fuente
1
Mi interpretación de JIT es que actúa como una memoria, donde las funciones de uso frecuente se 'almacenan' y se pasa por alto el costo de la compilación del código de bytes de Java al código nativo dependiente de ISA. Si esto es correcto, ¿por qué Java no compila completamente el código nativo desde el principio? ¿Esto reduciría cualquier tipo de compilación en tiempo de ejecución y haría que Java sea 'nativo' para la máquina?
Michael Choi
12

JIT significa Just-in-Time, lo que significa que el código se compila cuando es necesario, no antes del tiempo de ejecución.

Esto es beneficioso porque el compilador puede generar código optimizado para su máquina en particular. Un compilador estático, como su compilador C promedio, compilará todo el código en código ejecutable en la máquina del desarrollador. Por lo tanto, el compilador realizará optimizaciones basadas en algunos supuestos. Puede compilarse más lentamente y hacer más optimizaciones porque no ralentiza la ejecución del programa para el usuario.

Brian Lyttle
fuente
¿Por qué los códigos compilados no se almacenan en algún lugar de la computadora del usuario para que la próxima vez que se ejecute la aplicación JIT no tenga que volver a compilarlos?
omerfarukdogan
Buenas observaciones Es posible hacer esto, pero si realmente es beneficioso depende de la plataforma y el uso de la aplicación. La optimización de JIT no es necesariamente lo mismo que la optimización fuera de línea o anticipada, por lo que el beneficio solo puede ser "no JITting", lo que puede o no ayudar mucho.
Brian Lyttle
9

Después de que el compilador de Java haya generado el código de bytes (que es neutral en cuanto a la arquitectura), la ejecución será manejada por la JVM (en Java). El cargador cargará el código de bytes en JVM y luego se interpretará cada instrucción de bytes.

Cuando necesitamos llamar a un método varias veces, necesitamos interpretar el mismo código muchas veces y esto puede llevar más tiempo del necesario. Entonces tenemos los compiladores JIT (justo a tiempo). Cuando el byte ha sido cargado en JVM (su tiempo de ejecución), todo el código se compilará en lugar de interpretarse, ahorrando así tiempo.

Los compiladores JIT solo funcionan durante el tiempo de ejecución, por lo que no tenemos ninguna salida binaria.

Usuario
fuente
2
Todo el código no se compila cuando se carga en la JVM, ya que hay poca información (lea: guía) sobre cómo realizar la compilación. Tenga en cuenta que el rendimiento es el objetivo final. JIT es bastante selectivo: supervisa y selecciona los métodos más populares para la optimización. Y sigue haciendo esto hasta que se alcanza el nivel máximo de optimización para métodos individuales.
Yaw Boakye
7

Just In Time Compiler (JIT):
compila los códigos de bytes de Java en instrucciones de máquina de esa CPU específica.

Por ejemplo, si tenemos una declaración de bucle en nuestro código de Java:

while(i<10){
    // ...
    a=a+i;
    // ...
 }

El código de bucle anterior se ejecuta 10 veces si el valor de i es 0.

No es necesario compilar el código de bytes 10 veces una y otra vez, ya que la misma instrucción se ejecutará 10 veces. En ese caso, es necesario compilar ese código solo una vez y el valor se puede cambiar por la cantidad requerida de veces. Entonces, el compilador Just In Time (JIT) realiza un seguimiento de dichas declaraciones y métodos (como se dijo anteriormente) y compila dichos fragmentos de código de bytes en el código de la máquina para un mejor rendimiento.

Otro ejemplo similar es que una búsqueda de un patrón usando "Expresión regular" en una lista de cadenas / oraciones.

El compilador JIT no compila todo el código al código de la máquina. Compila código que tiene un patrón similar en tiempo de ejecución.

Consulte esta documentación de Oracle sobre Comprender JIT para leer más.

Anands23
fuente
"No es necesario compilar el código de bytes 10 veces una y otra vez, ya que la misma instrucción se ejecutará 10 veces", ¿qué pasa con un compilador normal? ¿Compila esta pieza varias veces?
TT_
4

Tiene un código que se incluye en algunos IL (lenguaje intermedio). Cuando ejecuta su programa, la computadora no entiende este código. Solo entiende el código nativo. Entonces, el compilador JIT compila su IL en código nativo sobre la marcha. Hace esto a nivel de método.

Charles Graham
fuente
2
¿Qué quiere decir "nivel de método"?
Koray Tugay
4

Sé que este es un hilo viejo, pero la optimización del tiempo de ejecución es otra parte importante de la compilación JIT que no parece discutirse aquí. Básicamente, el compilador JIT puede monitorear el programa mientras se ejecuta para determinar formas de mejorar la ejecución. Luego, puede hacer esos cambios sobre la marcha, durante el tiempo de ejecución. Optimización de Google JIT (javaworld tiene un artículo bastante bueno al respecto ) .

eze
fuente
3

Un compilador justo a tiempo (JIT) es una pieza de software que recibe una entrada no ejecutable y devuelve el código de máquina apropiado para su ejecución. Por ejemplo:

Intermediate representation    JIT    Native machine code for the current CPU architecture

     Java bytecode            --->        machine code
     Javascript (run with V8) --->        machine code

La consecuencia de esto es que para una determinada arquitectura de CPU se debe instalar el compilador JIT apropiado.

Compilador de diferencias, intérprete y JIT

Aunque puede haber excepciones en general cuando queremos transformar el código fuente en código de máquina, podemos usar:

  1. Compilador : toma el código fuente y devuelve un ejecutable
  2. Intérprete : ejecuta la instrucción del programa por instrucción. Toma un segmento ejecutable del código fuente y convierte ese segmento en instrucciones de máquina. Este proceso se repite hasta que todo el código fuente se transforma en instrucciones de máquina y se ejecuta.
  3. JIT : son posibles muchas implementaciones diferentes de un JIT, sin embargo, un JIT suele ser una combinación de un compilador y un intérprete. El JIT primero convierte los datos intermedios (por ejemplo, el código de bytes de Java) que recibe en lenguaje de máquina mediante interpretación. Un JIT a menudo puede detectar cuando una cierta parte del código se ejecuta a menudo y compilará esta parte para una ejecución más rápida.
Willem van der Veen
fuente
2

Jit significa compilador justo a tiempo. Jit es un programa que convierte el código de bytes de Java en instrucciones que se pueden enviar directamente al procesador.

El uso del compilador de Java justo a tiempo (realmente un segundo compilador) en la plataforma de sistema particular cumple el código de bytes en un código de sistema particular, una vez que el compilador jit vuelve a compilar el código, generalmente se ejecutará más rápidamente en la computadora.

El compilador justo a tiempo viene con la máquina virtual y se usa opcionalmente. Compila el código de bytes en código ejecutable específico de la plataforma que se ejecuta de inmediato.

usuario3459027
fuente
2

La compilación just-in-time (JIT), (también traducción dinámica o compilación en tiempo de ejecución ), es una forma de ejecutar código informático que implica la compilación durante la ejecución de un programa, en tiempo de ejecución, en lugar de antes de la ejecución .

La compilación de TI es una combinación de los dos enfoques tradicionales de traducción al código de máquina: compilación anticipada (AOT) e interpretación , y combina algunas ventajas y desventajas de ambos. La compilación JIT combina la velocidad del código compilado con la flexibilidad de interpretación .

Consideremos JIT utilizado en JVM,

Por ejemplo, los compiladores HotSpot JVM JIT generan optimizaciones dinámicas. En otras palabras, toman decisiones de optimización mientras se ejecuta la aplicación Java y generan instrucciones de máquina nativa de alto rendimiento destinadas a la arquitectura del sistema subyacente.

Cuando se elige un método para la compilación, la JVM alimenta su código de bytes al compilador Just-In-Time (JIT). El JIT necesita comprender la semántica y la sintaxis del bytecode antes de poder compilar el método correctamente. Para ayudar al compilador JIT a analizar el método, sus códigos de bytes se reformulan primero en una representación interna llamada árboles de rastreo, que se asemeja más al código de máquina que al código de bytes. El análisis y las optimizaciones se realizan en los árboles del método. Al final, los árboles se traducen al código nativo.

Un árbol de rastreo es una estructura de datos que se utiliza en la compilación en tiempo de ejecución del código de programación. Los árboles de rastreo se utilizan en un tipo de 'compilador justo a tiempo' que rastrea el código que se ejecuta durante los puntos calientes y lo compila. Consulte este .

Consulte:

principal
fuente
1

Un compilador que no es JIT toma el código fuente y lo transforma en código de bytes específico de la máquina en el momento de la compilación. Un compilador JIT toma el código de bytes agnóstico de la máquina que se generó en el momento de la compilación y lo transforma en código de bytes específico de la máquina en el tiempo de ejecución. El compilador JIT que utiliza Java es lo que permite que un solo binario se ejecute en una multitud de plataformas sin modificación.


fuente
0

El 20% del código de bytes se usa el 80% del tiempo. El compilador JIT obtiene estas estadísticas y optimiza este 20% del código de bytes para que se ejecute más rápido al agregar métodos en línea, eliminar bloqueos no utilizados, etc. y también crear el código de bytes específico para esa máquina. Estoy citando este artículo, me pareció útil. http://java.dzone.com/articles/just-time-compiler-jit-hotspot

Santosh budhe
fuente
No estoy seguro de por qué esto se marcó -1. Creo que el punto aquí es que las estadísticas de tiempo de ejecución se utilizan para ayudar a optimizar.
eze
Sí, pero la respuesta no lo expresó así. Literalmente, JIT no optimiza el 20% más caliente del código.
mabraham
0

JIT se refiere al motor de ejecución en pocas implementaciones de JVM, uno que es más rápido pero requiere más memoria, es un compilador justo a tiempo. En este esquema, los códigos de bytes de un método se compilan en código máquina nativo la primera vez que se invoca el método. El código de máquina nativo para el método se almacena en caché, por lo que puede reutilizarse la próxima vez que se invoque el mismo método.

Venkata Santhosh Piduri
fuente
2
Evitaría responder preguntas como esta si no proporciona algo nuevo / mejor. Si tiene alguna reacción, probablemente sea un voto negativo o una crítica: su respuesta es imprecisa. "JIT" no se limita a una máquina virtual Java , "más rápido pero usa más memoria" es un efecto probable pero no inherente al concepto JIT, y los métodos a menudo no se compilan en la primera invocación, sino después de varios cuando queda claro que Pasar tiempo en JIT'ing es ventajoso en general.
zapl
0

JVM realmente realiza pasos de compilación durante el tiempo de ejecución por razones de rendimiento. Esto significa que Java no tiene una separación de compilación-ejecución limpia. Primero realiza una compilación estática llamada del código fuente de Java a bytecode. Luego, este código de bytes se pasa a la JVM para su ejecución. Pero la ejecución de bytecode es lenta, por lo que la JVM mide con qué frecuencia se ejecuta el bytecode y cuando detecta un "punto de acceso" del código que se ejecuta con mucha frecuencia, realiza una compilación dinámica del código de byte al código de máquina del código de "punto de acceso". Así que, efectivamente, hoy los programas Java se ejecutan mediante ejecución de código de máquina.

hola.nitish
fuente
0

El compilador Just In Time, también conocido como compilador JIT, se utiliza para mejorar el rendimiento en Java. Está habilitado por defecto. Es una compilación realizada en tiempo de ejecución bastante antes. Java ha popularizado el uso del compilador JIT incluyéndolo en JVM.

Ganesh Giri
fuente