Compilación Ahead-of-time (AOT)

format_list_bulleted Contenido keyboard_arrow_down
ImprimirCitar

En informática, la compilación anticipada o compilación Ahead-of-time (AOT) es el acto de compilar un lenguaje de programación (a menudo) de nivel superior en un lenguaje de nivel inferior (a menudo) antes de la ejecución de un programa, generalmente en tiempo de compilación, para reducir la cantidad de trabajo necesario para realizar en tiempo de ejecución.

En la mayoría de los casos, se asocia con el acto de compilar un lenguaje de programación de nivel superior, como C o C++, o una representación intermedia, como el código de bytes de Java o el código de lenguaje intermedio común (CIL) de.NET Framework, en un lenguaje nativo (dependiente del sistema).) código de máquina para que el archivo binario resultante pueda ejecutarse de forma nativa, como un compilador nativo estándar. Cuando se utiliza en este contexto específico, a menudo se considera lo opuesto a la compilación justo a tiempo (JIT).

Hablando de manera más general, los idiomas de destino de una compilación AOT no son necesariamente específicos del código de máquina nativo, sino que se definen de manera bastante arbitraria. Algunos artículos académicos usan esta palabra para indicar el acto de compilar el código de bytes de Java en C o el momento en que se realiza la canalización de optimización. Un proyecto académico utiliza esta palabra para indicar el acto de precompilar JavaScript en un IR optimizado dependiente de la máquina para V8 (motor de JavaScript) y en un código de bytes independiente de la máquina para JavaScriptCore. Algunas implementaciones de lenguajes industriales (por ejemplo, el motor JavaScript de Clojure y Hermes) usan esta palabra para referirse al acto de precompilar el lenguaje de origen en el código de bytes específico de la máquina virtual. Angular (marco web) usa esta palabra para referirse a convertir su plantilla HTML y TypeScript a JavaScript.

De hecho, dado que todas las compilaciones estáticas se realizan técnicamente con anticipación, esta redacción en particular se usa a menudo para enfatizar algún tipo de ventajas de rendimiento del acto de compilación previa. Por lo tanto, el acto de compilar código de bytes de Java a Java rara vez se denomina AOT, ya que generalmente es un requisito, no una optimización.

Reducción de la sobrecarga de tiempo de ejecución

Algunos lenguajes de programación con un tiempo de ejecución de código administrado que se puede compilar en una representación intermedia, utilizan la compilación justo a tiempo (JIT). Esto, brevemente, compila el código intermedio en código de máquina para una ejecución nativa mientras se ejecuta el código intermedio, lo que puede ralentizar el rendimiento de una aplicación. La compilación anticipada elimina la necesidad de este paso al ocurrir antes de la ejecución en lugar de durante la ejecución.

La compilación anticipada para lenguajes escritos dinámicamente en código de máquina nativo u otro código de bytes de VM estático es posible solo en un número limitado de casos. Por ejemplo, el compilador AOT High Performance Erlang Project (HiPE) para el lenguaje Erlang puede hacer esto debido a las técnicas avanzadas de reconstrucción de tipo estático y las especulaciones de tipo.

En la mayoría de las situaciones con programas y bibliotecas completamente compilados con AOT, es posible descartar una fracción útil de un entorno de tiempo de ejecución, ahorrando así espacio en disco, memoria, duración de la batería y tiempos de inicio (sin fase de calentamiento JIT), etc. Debido a esto, puede ser útil en dispositivos integrados o móviles.

Compensaciones de rendimiento

Los compiladores AOT pueden realizar optimizaciones de código complejas y avanzadas, que en la mayoría de los casos de JITing se considerarán demasiado costosas. Por el contrario, AOT generalmente no puede realizar algunas optimizaciones posibles en JIT, como la optimización guiada por perfil de tiempo de ejecución (PGO), la propagación pseudoconstante o la función virtual indirecta en línea. AOT debe compilar en una arquitectura de destino, mientras que JIT puede compilar el código para hacer el mejor uso de la CPU real en la que se ejecuta, incluso años después de que se haya lanzado el software.

Además, los compiladores JIT pueden optimizar de forma especulativa el código caliente haciendo suposiciones sobre el código. El código generado se puede desoptimizar si una suposición especulativa luego resulta incorrecta. Dicha operación ralentiza el rendimiento del software en ejecución hasta que el código se vuelve a optimizar mediante la optimización adaptativa. Un compilador AOT no puede hacer tales suposiciones y necesita inferir tanta información como sea posible en el momento de la compilación. Necesita recurrir a un código menos especializado porque no puede saber qué tipos pasarán por un método. Dichos problemas se pueden aliviar mediante optimizaciones guiadas por perfiles. Pero incluso en este caso, el código generado no se puede adaptar dinámicamente al perfil de tiempo de ejecución cambiante como lo haría un compilador JIT.