Compilación anticipada de Xamarin.Mac
Información general
La compilación anticipada (AOT) es una técnica de optimización eficaz para mejorar el rendimiento de inicio. Sin embargo, también afecta, en gran mediad, el tiempo de compilación, el tamaño de la aplicación y la ejecución del programa. Para comprender los inconvenientes que impone, vamos a profundizar un poco en la compilación y ejecución de una aplicación.
El código escrito en lenguajes administrados, como C# y F#, se compila en una representación intermedia denominada IL (lenguaje intermedio). Este IL, almacenado en la biblioteca y los ensamblados de programa, es relativamente compacto y portátil entre arquitecturas de procesador. IL, sin embargo, es solo un conjunto intermedio de instrucciones y en algún momento, ese IL necesitará ser traducido a código máquina específico para el procesador.
Hay dos puntos en los que se puede realizar este procesamiento:
- Cuando es necesario (JIT): durante el inicio y la ejecución de la aplicación, el IL se compila en memoria en código máquina.
- Anticipada (AOT): durante la compilación, el IL se compila y escribe en bibliotecas nativas y se almacena dentro de la agrupación de aplicaciones.
Cada opción tiene una serie de ventajas y desventajas:
- JIT
- Tiempo de inicio: la compilación JIT debe realizarse al iniciarse. Para la mayoría de las aplicaciones, este tiempo es del orden de 100 ms, pero para aplicaciones de gran tamaño puede ser significativamente mayor.
- Ejecución : ya que el código JIT se puede optimizar para el procesador específico que se usa, se puede generar código ligeramente mejor. En la mayoría de aplicaciones, se trata de unos pocos puntos porcentuales más rápidos como máximo.
- AOT
- Tiempo de inicio: la carga de dylibs precompilados es significativamente más rápida que la de ensamblados JIT.
- Espacio en disco: sin embargo, esos dylibs pueden tomar una cantidad significativa de espacio en disco. Dependiendo de los ensamblados anticipados (AOT), puede duplicar o más el tamaño de la parte de código de la aplicación.
- Tiempo de compilación: la compilación AOT es significativamente más lenta que JIT y su uso ralentizará las compilaciones. Esta ralentización puede oscilar entre segundos y hasta un minuto o más, según el tamaño y el número de ensamblados compilados.
- Ofuscación: dado que el IL, que es mucho más fácil de descifrar que el código máquina, no es necesariamente requerido, puede ser despojado para ayudar a ofuscar código confidencial. Esto requiere la opción "Híbrida", que se describe a continuación.
Habilitación de AOT
Las opciones de AOT se agregarán al panel Compilación de Mac en una actualización futura. Hasta entonces, habilitar AOT requiere pasar un argumento de línea de comandos a través del campo "Argumentos mmp adicionales" en Compilación de Mac. Las opciones son las siguientes:
--aot[=VALUE] Specify assemblies that should be AOT compiled
- none - No AOT (default)
- all - Every assembly in MonoBundle
- core - Xamarin.Mac, System, mscorlib
- sdk - Xamarin.Mac.dll and BCL assemblies
- |hybrid after option enables hybrid AOT which
allows IL stripping but is slower (only valid
for 'all')
- Individual files can be included for AOT via +
FileName.dll and excluded via -FileName.dll
Examples:
--aot:all,-MyAssembly.dll
--aot:core,+MyOtherAssembly.dll,-mscorlib.dll
AOT híbrida
Durante la ejecución de una aplicación macOS, el runtime utiliza por defecto código máquina cargado desde las librerías nativas producidas por la compilación AOT. Sin embargo, hay algunas áreas de código, como trampolines, donde la compilación JIT puede producir resultados significativamente más optimizados. Esto requiere que el IL de los ensamblados administrados esté disponible. En iOS, las aplicaciones tienen restringido el uso de la compilación JIT; esas secciones de código también se compilan con AOT.
La opción híbrida le indica al compilador que compile estas secciones (como iOS), pero también le indica que suponga que el IL no estará disponible en tiempo de ejecución. Este IL se puede eliminar después de la compilación. Como se ha señalado anteriormente, el runtime se verá obligado a utilizar rutinas menos optimizadas en algunos lugares.
Consideraciones a tener en cuenta
Las consecuencias negativas del uso de AOT aumentan con el tamaño y el número de conjuntos procesados. La plataforma de destino Completa, por ejemplo, contiene una biblioteca de clases base (BCL) significativamente mayor que la Moderna y, por tanto, AOT tardará significativamente más tiempo y generará agrupaciones más grandes. Esto se ve agravado por la incompatibilidad del marco de destino Completa con Vinculación, que elimina el código no utilizado. Considere la posibilidad de mover la aplicación a Moderna y habilitar la vinculación para obtener los mejores resultados.
Una ventaja adicional de AOT incluye las interacciones mejoradas con cadenas de herramientas de depuración y generación de perfiles nativas. Dado que una gran mayoría del código base se compilará con antelación, tendrá nombres de función y símbolos que son más fáciles de leer dentro de informes de bloqueo nativos, generación de perfiles y depuración. Las funciones generadas por JIT no tienen estos nombres y a menudo aparecen como desplazamientos hexadecimales sin nombre que son muy difíciles de resolver.