Compilación de Xamarin.Mac con antelación
Información general
La compilación con antelación (AOT) es una técnica de optimización eficaz para mejorar el rendimiento de inicio. Sin embargo, también afecta al tiempo de compilación, el tamaño de la aplicación y la ejecución del programa de maneras profundas. Para comprender los contras 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. Este IL, almacenado en los ensamblados de biblioteca y 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, il tendrá que traducirse en código de máquina específico del procesador.
Hay dos puntos en los que se puede realizar este procesamiento:
- Just-In-Time (JIT): durante el inicio y la ejecución de la aplicación, el IL se compila en memoria en código de máquina.
- Con antelación (AOT): durante la compilación, el IL se compila y escribe en bibliotecas nativas y se almacena en el paquete de aplicaciones.
Cada opción tiene una serie de ventajas y ventajas:
- JIT
- Tiempo de inicio: la compilación JIT debe realizarse durante el inicio. Para la mayoría de las aplicaciones, esto está en el orden de 100 ms, pero para las aplicaciones grandes este tiempo puede ser mucho más.
- Ejecución: como 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 las aplicaciones, esto es unos pocos puntos porcentuales más rápido como máximo.
- AOT
- Tiempo de inicio: la carga de dylibs precomppiladas es significativamente más rápida que los ensamblados JIT.
- Espacio en disco: sin embargo, esas bibliotecas pueden tomar una cantidad significativa de espacio en disco. Dependiendo de qué ensamblados se AOTed, 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 de AOT es significativamente más lenta que JIT y ralentizará las compilaciones que lo usan. Esta ralentización puede oscilar entre segundos y un minuto o más, según el tamaño y el número de ensamblados compilados.
- Ofuscación: como el IL, que es significativamente más fácil de realizar ingeniería inversa que el código de máquina, no es necesariamente necesario, se puede quitar para ayudar a ofuscar el código confidencial. Esto requiere la opción "Híbrido" 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, la habilitación de AOT requiere pasar un argumento de línea de comandos a través del campo "Argumentos mmp adicionales" en Mac Build. 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íbrido
Durante la ejecución de una aplicación macOS, el entorno de ejecución usa de forma predeterminada código de máquina cargado desde las bibliotecas nativas producidas por la compilación de AOT. Sin embargo, hay algunas áreas de código, como las tablas, donde la compilación JIT puede producir resultados significativamente más optimizados. Esto requiere que el IL de ensamblados administrados esté disponible. En iOS, las aplicaciones están restringidas a cualquier uso de la compilación JIT; esas secciones de código también están compiladas por AOT.
La opción híbrida indica al compilador que compile estas secciones (como iOS), pero también que suponga que el IL no estará disponible en tiempo de ejecución. Este IL se puede quitar después de la compilación. Como se indicó anteriormente, el tiempo de ejecución se verá obligado a usar rutinas menos optimizadas en algunos lugares.
Otras consideraciones
Las consecuencias negativas de la escala de AOT con los tamaños y el número de ensamblados procesados. El marco de destino Full, por ejemplo, contiene una biblioteca de clases base (BCL) significativamente mayor que modern y, por tanto, AOT tarda mucho más tiempo y genera agrupaciones más grandes. Esto se suma a la incompatibilidad de la plataforma de destino completa con la vinculación, que elimina el código no usado. Considere la posibilidad de mover la aplicación a Modern y habilitar la vinculación para obtener los mejores resultados.
Una ventaja adicional de AOT viene con las interacciones mejoradas con las 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 los informes de bloqueo nativos, la generación de perfiles y la depuración. Las funciones generadas por JIT no tienen estos nombres y a menudo se muestran como desplazamientos hexadecimales sin nombre que son muy difíciles de resolver.