Compilación justo a tiempo


En informática , la compilación justo a tiempo ( JIT ) (también traducción dinámica o compilaciones en tiempo de ejecución ) [1] 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. [2] Esto puede consistir en la traducción del código fuente, pero es más común la traducción del código de bytes al código de máquina., que luego se ejecuta directamente. Un sistema que implementa un compilador JIT generalmente analiza continuamente el código que se ejecuta e identifica partes del código donde la aceleración obtenida de la compilación o recompilación superaría la sobrecarga de compilar ese código.

La compilación JIT es una combinación de los dos enfoques tradicionales para la traducción a código de máquina: compilación anticipada (AOT) e interpretación , y combina algunas ventajas y desventajas de ambos. [2] Aproximadamente, la compilación JIT combina la velocidad del código compilado con la flexibilidad de interpretación, con la sobrecarga de un intérprete y la sobrecarga adicional de compilar y vincular (no solo interpretar). La compilación JIT es una forma de compilación dinámica y permite la optimización adaptativa , como la recompilación dinámica y aceleraciones específicas de microarquitectura . [nota 1] [3]La interpretación y la compilación JIT son particularmente adecuadas para los lenguajes de programación dinámicos , ya que el sistema de tiempo de ejecución puede manejar tipos de datos enlazados en tiempo de ejecución y hacer cumplir las garantías de seguridad.

El primer compilador JIT publicado generalmente se atribuye al trabajo en LISP de John McCarthy en 1960. [4] En su artículo seminal Funciones recursivas de expresiones simbólicas y su cálculo por máquina, Parte I , menciona funciones que se traducen durante el tiempo de ejecución, ahorrando así la necesidad de guardar la salida del compilador en tarjetas perforadas [5] (aunque esto se conocería con mayor precisión como un " sistema Compile and Go "). Otro ejemplo temprano fue el de Ken Thompson , quien en 1968 dio una de las primeras aplicaciones de expresiones regulares , aquí para la coincidencia de patrones en el editor de texto QED.. [6] Para mayor velocidad, Thompson implementó la coincidencia de expresiones regulares mediante JITing con el código IBM 7094 en el Sistema de tiempo compartido compatible . [4] Una técnica influyente para derivar código compilado a partir de la interpretación fue iniciada por James G. Mitchell en 1970, que implementó para el lenguaje experimental LC² . [7] [8]

Smalltalk (c. 1983) fue pionero en nuevos aspectos de las compilaciones JIT. Por ejemplo, la traducción a código de máquina se realizó bajo demanda y el resultado se almacenó en caché para su uso posterior. Cuando la memoria escaseaba, el sistema borraba parte de este código y lo regeneraba cuando se necesitaba de nuevo. [2] [9] El lenguaje Self de Sun mejoró ampliamente estas técnicas y en un momento fue el sistema Smalltalk más rápido del mundo; logrando hasta la mitad de la velocidad de C optimizado [10] pero con un lenguaje completamente orientado a objetos.

Self fue abandonado por Sun, pero la investigación se centró en el lenguaje Java. El término "Compilación justo a tiempo" se tomó prestado del término de fabricación " Justo a tiempo " y popularizado por Java, con James Gosling usando el término de 1993. [11] Actualmente, la mayoría de las implementaciones de Java Virtual Machine utilizan JITing . , ya que HotSpot se basa en esta base de investigación y la utiliza ampliamente.

El proyecto Dynamo de HP era un compilador JIT experimental en el que el formato de 'código de bytes' y el formato de código de máquina eran los mismos; el sistema convirtió el código de máquina PA-6000 en código de máquina PA-8000 . [12] De manera contraria a la intuición, esto resultó en aceleraciones, en algunos casos del 30 %, ya que esto permitió optimizaciones a nivel de código de máquina, por ejemplo, código integrado para un mejor uso de caché y optimizaciones de llamadas a bibliotecas dinámicas y muchas otras funciones de tiempo de ejecución. optimizaciones que los compiladores convencionales no pueden intentar. [13] [14]