ejecucion compilador compilacion algoritmo compilation jit

compilation - compilador - compilacion y ejecucion de un algoritmo



¿Cuáles son las ventajas de la compilación justo a tiempo frente a la compilación anticipada? (9)

  1. Mayor portabilidad: el entregable (byte-code) permanece portátil

  2. Al mismo tiempo, más específico de la plataforma: debido a que la compilación JIT se lleva a cabo en el mismo sistema que se ejecuta el código, puede ser muy, muy preciso para ese sistema en particular. Si realiza una compilación anticipada (y aún desea enviar el mismo paquete a todos), debe comprometerse.

  3. Las mejoras en la tecnología del compilador pueden tener un impacto en los programas existentes. Un mejor compilador de C no le ayuda en absoluto con los programas ya implementados. Un mejor compilador JIT mejorará el rendimiento de los programas existentes. El código Java que escribiste hace diez años se ejecutará más rápido hoy.

  4. Adaptación a métricas en tiempo de ejecución. Un compilador JIT no solo puede mirar el código y el sistema de destino, sino también cómo se usa el código. Puede instrumentar el código en ejecución y tomar decisiones sobre cómo optimizar de acuerdo con, por ejemplo, qué valores suelen tener los parámetros del método.

Tiene razón al agregar JIT al costo de inicio, por lo que hay una limitación de tiempo para ello, mientras que la compilación anticipada puede llevar todo el tiempo que quiera. Esto lo hace más apropiado para aplicaciones tipo servidor, donde el tiempo de inicio no es tan importante y es aceptable una "fase de calentamiento" antes de que el código sea realmente rápido.

Supongo que sería posible almacenar el resultado de una compilación JIT en algún lugar, para que pueda ser reutilizado la próxima vez. Eso le daría una compilación "anticipada" para la segunda ejecución del programa. Tal vez las personas inteligentes de Sun y Microsoft opinan que un JIT nuevo ya es lo suficientemente bueno y la complejidad adicional no merece la pena.

Lo he estado pensando últimamente, y me parece que la mayoría de las ventajas otorgadas a la compilación JIT deberían atribuirse más o menos al formato intermedio, y que jits en sí mismo no es una buena forma de generar código.

Así que estos son los principales argumentos de compilación pro-JIT que normalmente escucho:

  1. La compilación justo a tiempo permite una mayor portabilidad. ¿No es eso atribuible al formato intermedio? Quiero decir, nada le impide compilar su bytecode virtual en el bytecode nativo una vez que lo tenga en su máquina. La portabilidad es un problema en la fase de ''distribución'', no durante la fase de ''ejecución''.
  2. Bien, entonces, ¿qué hay de generar código en tiempo de ejecución? Bueno, lo mismo se aplica. Nada le impide integrar un compilador justo a tiempo para una necesidad real justo a tiempo en su programa nativo.
  3. Pero el tiempo de ejecución lo compila en un código nativo una sola vez, y almacena el ejecutable resultante en algún tipo de caché en algún lugar de su disco duro. Si seguro. Pero ha optimizado su programa bajo restricciones de tiempo, y no lo está mejorando de ahí en adelante. Vea el siguiente párrafo.

No es como si la compilación anticipada tampoco tuviera ventajas. La compilación justo a tiempo tiene limitaciones de tiempo: no puede hacer que el usuario final espere eternamente mientras se inicia el programa, por lo que tiene un compromiso que hacer en alguna parte. La mayoría de las veces solo optimizan menos. Un amigo mío tenía evidencia de que las funciones de alineación y los bucles de desenrollamiento "manualmente" (ofuscando el código fuente en el proceso) tuvieron un impacto positivo en el rendimiento de su programa de procesamiento de números C # ; hacer lo mismo por mi parte, con mi programa de C cumpliendo la misma tarea, no dio resultados positivos, y creo que esto se debe a las extensas transformaciones que mi compilador pudo realizar.

Y, sin embargo, estamos rodeados de programas jitted. C # y Java están en todas partes, los scripts de Python pueden compilarse con algún tipo de código de bytes, y estoy seguro de que muchos otros lenguajes de programación hacen lo mismo. Debe haber una buena razón por la que me estoy perdiendo. Entonces, ¿qué hace que la compilación justo a tiempo sea tan superior a la compilación anticipada ?

EDITAR Para aclarar algunas confusiones, quizás sería importante afirmar que estoy a favor de una representación intermedia de ejecutables. Esto tiene muchas ventajas (y, en realidad, la mayoría de los argumentos para una compilación justo a tiempo son en realidad argumentos para una representación intermedia). Mi pregunta es acerca de cómo deben compilarse a código nativo.

La mayoría de los tiempos de ejecución (o compiladores en este caso) preferirán compilarlos justo a tiempo o antes de tiempo. Como la compilación anticipada me parece una mejor alternativa porque el compilador tiene más tiempo para realizar optimizaciones, me pregunto por qué Microsoft, Sun y todos los demás están al revés. Tengo dudas acerca de las optimizaciones relacionadas con la creación de perfiles, ya que mi experiencia con programas compilados justo a tiempo muestra malas optimizaciones básicas.

Utilicé un ejemplo con código C solo porque necesitaba un ejemplo de compilación anticipada frente a compilación justo a tiempo . El hecho de que el código C no se haya emitido a una representación intermedia es irrelevante para la situación, ya que solo necesitaba demostrar que la compilación anticipada puede producir mejores resultados inmediatos.


  1. Mejor apoyo a la reflexión. Esto se podría hacer en principio en un programa compilado con anticipación, pero casi nunca parece ocurrir en la práctica.

  2. Optimizaciones que a menudo solo pueden resolverse observando el programa dinámicamente. Por ejemplo, incorporando funciones virtuales, el análisis de escape para convertir las asignaciones de pila en asignaciones de almacenamiento dinámico, y bloquear el engrosamiento.


La página de la herramienta ngen derramó los beans (o al menos proporcionó una buena comparación de imágenes nativas con las imágenes compiladas con JIT). Los ejecutables que se compilan con anticipación suelen tener los siguientes beneficios:

  1. Las imágenes nativas se cargan más rápido porque no tienen muchas actividades de inicio y requieren una cantidad estática de menos memoria (la memoria requerida por el compilador JIT);
  2. Las imágenes nativas pueden compartir el código de la biblioteca, mientras que las imágenes compiladas con JIT no pueden.

Los ejecutables compilados Just-in-time normalmente tienen la ventaja en estos casos:

  1. Las imágenes nativas son más grandes que sus contrapartes de bytecode;
  2. Las imágenes nativas deben regenerarse siempre que se modifique el ensamblaje original o una de sus dependencias.

La necesidad de regenerar una imagen que se compila antes de tiempo cada vez que uno de sus componentes es una gran desventaja para las imágenes nativas. Por otro lado, el hecho de que las imágenes compiladas con JIT no puedan compartir el código de la biblioteca puede causar un impacto grave en la memoria. El sistema operativo puede cargar cualquier biblioteca nativa en una ubicación física y compartir sus partes inmutables con cada proceso que quiera usarlo, lo que conlleva un importante ahorro de memoria, especialmente con los marcos del sistema que utiliza prácticamente todos los programas. (Imagino que esto se ve contrarrestado por el hecho de que los programas compilados por JIT solo compilan lo que realmente usan).

La consideración general de Microsoft al respecto es que las aplicaciones grandes generalmente se benefician de la compilación anticipada, mientras que las pequeñas generalmente no lo hacen.


La diferencia entre plataforma-navegador-dinámico y plataforma-navegador es la forma en que se compilará su aplicación angular. El uso de la plataforma dinámica hace que el envío angular del compilador Just-in-Time al front-end, así como su aplicación. Lo que significa que su aplicación se está compilando en el lado del cliente. Por otro lado, el uso del navegador de plataforma conduce a una versión precompilada de su aplicación con anticipación de tiempo que se envía al navegador. Lo que generalmente significa un paquete significativamente más pequeño que se envía al navegador. La documentación angular2 para el arranque en https://angular.io/docs/ts/latest/guide/ngmodule.html#!#bootstrap explica con más detalle.


La lógica simple nos dice que compilar un enorme programa de tamaño MS Office incluso a partir de códigos de bytes simplemente tomará demasiado tiempo. Terminará con una gran hora de inicio y eso asustará a cualquiera de su producto. Claro, puede precompilar durante la instalación, pero esto también tiene consecuencias.

Otra razón es que no se utilizarán todas las partes de la aplicación. JIT compilará solo las partes que le importan al usuario, dejando potencialmente el 80% del código sin tocar, ahorrando tiempo y memoria.

Y finalmente, la compilación JIT puede aplicar optimizaciones que los compiladores normales no pueden. Como incorporar métodos virtuales o partes de los métodos con árboles traza . Lo que, en teoría, puede hacerlos más rápidos.


Parece que esta idea ha sido implementada en lenguaje Dart:

https://hackernoon.com/why-flutter-uses-dart-dd635a054ebf

La compilación JIT se utiliza durante el desarrollo, utilizando un compilador que es especialmente rápido. Luego, cuando una aplicación está lista para su lanzamiento, se compila AOT. En consecuencia, con la ayuda de herramientas y compiladores avanzados, Dart puede ofrecer lo mejor de ambos mundos: ciclos de desarrollo extremadamente rápidos y tiempos de arranque y ejecución rápidos.


Tal vez tenga que ver con el enfoque moderno de la programación. Sabes, hace muchos años escribirías tu programa en una hoja de papel, otras personas lo transformarían en una pila de tarjetas perforadas y alimentarían LA computadora, y mañana por la mañana recibirías un volcado en un rollo de papel que pesaba media libra. Todo eso te obligó a pensar mucho antes de escribir la primera línea de código.

Esos días han quedado atrás. Cuando use un lenguaje de scripting como PHP o JavaScript, puede probar cualquier cambio inmediatamente. Ese no es el caso de Java, aunque los servidores de aplicaciones le brindan un despliegue dinámico. Por lo tanto, es muy útil que los programas Java puedan compilarse rápidamente , ya que los compiladores de códigos de bytes son bastante sencillos.

Pero, no existe tal cosa como lenguajes solo JIT. Los compiladores anticipados han estado disponibles para Java durante bastante tiempo, y más recientemente, Mono lo introdujo en CLR. De hecho, MonoTouch es posible en absoluto debido a la compilación AOT, ya que las aplicaciones no nativas están prohibidas en la tienda de aplicaciones de Apple.


También he estado tratando de entender esto porque vi que Google se está moviendo hacia la sustitución de su Máquina Virtual Dalvik (esencialmente otra Máquina Virtual Java como HotSpot) con Android Run Time (ART), que es un compilador AOT, pero Java usualmente usa HotSpot , que es un compilador JIT. Aparentemente, ARM es ~ 2 veces más rápido que Dalvik ... así que pensé "¿por qué Java no usa AOT también?". De todos modos, de lo que puedo deducir, la principal diferencia es que JIT utiliza la optimización adaptativa durante el tiempo de ejecución, lo que (por ejemplo) permite SOLAMENTE aquellas partes del código de bytes que se ejecutan con frecuencia para compilarse en el código nativo; mientras que AOT compila todo el código fuente en código nativo, y el código de una cantidad menor se ejecuta más rápido que el código de una cantidad mayor.
Tengo que imaginar que la mayoría de las aplicaciones de Android se componen de una pequeña cantidad de código, por lo que en promedio tiene más sentido compilar todo el código fuente a código nativo AOT y evitar los gastos generales asociados con la interpretación / optimización.


Una de las ventajas del JIT que no veo aquí es la capacidad de alinear / optimizar a través de ensamblajes separados / dlls / jars (por simplicidad, voy a usar "ensamblajes" de aquí en adelante).

Si su aplicación hace referencia a ensamblajes que pueden cambiar después de la instalación (por ejemplo, bibliotecas preinstaladas, bibliotecas de marco, complementos), entonces un modelo de "compilación en la instalación" debe abstenerse de incorporar métodos a través de los límites de ensamblaje. De lo contrario, cuando se actualice el ensamblaje al que se hace referencia, tendríamos que encontrar todos los bits de código en línea al hacer referencia a los ensamblajes en el sistema y reemplazarlos con el código actualizado.

En un modelo JIT, podemos en línea libremente a través de ensamblajes porque solo nos importa generar un código de máquina válido para una única ejecución durante la cual el código subyacente no cambie.