Implementación nativa de AOT en iOS y Mac Catalyst
La implementación nativa de AOT genera una aplicación de interfaz de usuario de aplicación multiplataforma de .NET (.NET MAUI) en iOS y Mac Catalyst que se ha compilado con antelación (AOT) en código nativo. AOT nativo realiza análisis de programas estáticos, recorte completo de la aplicación, que es agresivo al quitar código al que no se hace referencia estáticamente y a la generación de código de antemano.
La publicación e implementación de una aplicación AOT nativa genera las siguientes ventajas:
- Tamaño reducido del paquete de la aplicación.
- Tiempo de inicio más rápido.
- Tiempo de compilación más rápido.
AOT nativo introducirá limitaciones en el uso de determinados aspectos del entorno de ejecución de .NET y solo debe usarse en escenarios en los que el tamaño y el rendimiento de la aplicación sean importantes. Necesitará adaptar las aplicaciones a los requisitos nativos de AOT, lo que significa asegurarse de que son totalmente recortados y compatibles con AOT. Para obtener más información sobre las limitaciones de AOT nativas, consulte Limitaciones de AOT nativas.
Cuando la implementación de AOT nativa está habilitada, el sistema de compilación analiza el código y todas sus dependencias para comprobar si es adecuado para el recorte completo y la compilación AOT. Si se detectan incompatibilidades, se generan advertencias de recorte y AOT. Una única advertencia de recorte o AOT significa que la aplicación no es compatible con la implementación de AOT nativa y que podría no funcionar correctamente. Por lo tanto, al compilar una aplicación para la implementación de AOT nativa, debe revisar y corregir todas las advertencias de recorte y AOT. Si no se hace esto, se pueden producir excepciones en tiempo de ejecución, ya que se podría haber quitado el código necesario. Si suprime las advertencias, la aplicación implementada con AOT debe probarse exhaustivamente para comprobar que la funcionalidad no ha cambiado de la aplicación no implementada. Para obtener más información, vea Introducción a las advertencias de recorte e Introducción a las advertencias de AOT.
Nota:
Puede haber casos en los que la corrección del recorte y las advertencias de AOT no son posibles, como cuando se producen para bibliotecas de terceros. En tales casos, las bibliotecas de terceros deberán actualizarse para que sean totalmente compatibles.
Ventajas nativas de rendimiento de AOT
La publicación e implementación de una aplicación AOT nativa genera una aplicación que normalmente es de hasta 2,5x más pequeña y una aplicación que se inicia normalmente hasta 2 veces más rápido. Sin embargo, las ventajas exactas de rendimiento dependen de varios factores que incluyen la plataforma que se usa, el dispositivo en el que se ejecuta la aplicación y la propia aplicación.
Importante
En los gráficos siguientes se muestran las ventajas de rendimiento típicas de la implementación nativa de AOT para una dotnet new maui
aplicación en iOS y Mac Catalyst. Sin embargo, los datos exactos dependen del hardware y pueden cambiar en futuras versiones.
En el gráfico siguiente se muestra el tamaño del paquete de la aplicación para una dotnet new maui
aplicación en iOS y Mac Catalyst en diferentes modelos de implementación:
En el gráfico anterior se muestra que, normalmente, AOT nativo genera más de 2 veces aplicaciones más pequeñas para iOS y Mac Catalyst en comparación con el modelo de implementación predeterminado.
En el gráfico siguiente se muestra el tiempo medio de inicio, en hardware específico, para una dotnet new maui
aplicación en iOS y Mac Catalyst en la implementación mono y nativa de AOT:
En el gráfico anterior se muestra que AOT nativo normalmente tiene hasta 2 veces más rápidos tiempos de inicio en dispositivos iOS y un tiempo de inicio 1,2x más rápido en Mac Catalyst, en comparación con la implementación mono.
En el gráfico siguiente se muestra el tiempo medio de compilación, en hardware específico, para una dotnet new maui
aplicación en iOS y Mac Catalyst en diferentes modelos de implementación:
En el gráfico anterior se muestra que, normalmente, AOT nativo tiene hasta 2,8 veces más rápidos tiempos de compilación en dispositivos iOS en comparación con el modelo de implementación predeterminado. Para Mac Catalyst, los tiempos de compilación son comparables para las aplicaciones rid únicas arm64, pero son ligeramente más lentas para las aplicaciones universales en comparación con la implementación mono.
Importante
En muchos escenarios, AOT nativo producirá aplicaciones más pequeñas y rápidas. Sin embargo, en algunos escenarios es posible que AOT nativo no genere aplicaciones más pequeñas y más rápidas. Por lo tanto, es importante probar y generar perfiles de la aplicación para determinar el resultado de habilitar la implementación nativa de AOT.
Publicación mediante AOT nativo
El modelo de implementación de AOT nativo está habilitado con la $(PublishAot)
propiedad build y el dotnet publish
comando . En el ejemplo siguiente se muestra cómo modificar un archivo de proyecto para habilitar la implementación nativa de AOT en iOS y Mac Catalyst:
<PropertyGroup>
<!-- enable trimming and AOT analyzers on all platforms -->
<IsAotCompatible>true</IsAotCompatible>
<!-- select platforms to use with NativeAOT -->
<PublishAot Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">true</PublishAot>
<PublishAot Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">true</PublishAot>
</PropertyGroup>
Al establecer la $(IsAotCompatible)
propiedad true
build en , para todas las plataformas, se habilitan los analizadores de recorte y AOT. Estos analizadores le ayudan a identificar el código que no es compatible con el recorte o AOT.
Establecer condicionalmente $(PublishAot)
true
en , para iOS y Mac Catalyst, permite el análisis dinámico del uso de código durante la compilación y la compilación AOT nativa durante la publicación. El análisis de AOT nativo incluye todo el código de la aplicación y todas las bibliotecas de las que depende la aplicación.
Advertencia
La $(PublishAot)
propiedad build no debe estar condicionada por la configuración de compilación. Esto se debe a que los modificadores de características de recorte están habilitados o deshabilitados en función del valor de la $(PublishAot)
propiedad de compilación, y las mismas características deben habilitarse o deshabilitarse en todas las configuraciones de compilación para que el código se comporte de forma idéntica. Para obtener más información sobre el recorte de conmutadores de características, consulte Trimming feature switches (Recorte de conmutadores de características).
La única manera de comprobar que una aplicación AOT nativa funciona correctamente es publicarla mediante dotnet publish
y comprobar que no hay advertencias de recorte o AOT generadas por el código y sus dependencias. En concreto, dotnet build -t:Publish
no es equivalente a dotnet publish
.
Use el siguiente dotnet publish
comando para publicar la aplicación en iOS y Mac Catalyst mediante la implementación nativa de AOT:
# iOS
dotnet publish -f net9.0-ios -r ios-arm64
# Mac Catalyst
dotnet publish -f net9.0-maccatalyst -r maccatalyst-arm64
dotnet publish -f net9.0-maccatalyst -r maccatalyst-x64
# Universal Mac Catalyst apps
# (when <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> is set in the project file)
dotnet publish -f net9.0-maccatalyst
Sugerencia
Publique aplicaciones con frecuencia para detectar problemas de recorte o AOT al principio del ciclo de vida de desarrollo.
Limitaciones de AOT nativas
AOT nativo introducirá limitaciones en el uso de determinados aspectos del entorno de ejecución de .NET y solo debe usarse en escenarios en los que el tamaño y el rendimiento de la aplicación sean importantes. Necesitará adaptar las aplicaciones a los requisitos nativos de AOT, lo que significa asegurarse de que son totalmente recortados y compatibles con AOT, y esto puede requerir mucho trabajo. Además de las limitaciones de .NET de la implementación de AOT nativa, la implementación de AOT nativa para .NET MAUI tiene limitaciones adicionales.
Es posible que las bibliotecas de terceros de las aplicaciones no sean compatibles con AOT. La única manera de asegurarse de que una biblioteca está recortando y que AOT es compatible con publicar la aplicación mediante la implementación nativa de AOT y el dotnet publish
comando, y ver si el compilador de AOT nativo genera advertencias para la biblioteca. Para obtener información sobre cómo hacer que sus propias bibliotecas sean compatibles con AOT, consulte Cómo hacer que las bibliotecas sean compatibles con AOT nativos.
Reflexión y código dinámico
La implementación de AOT nativa limita el uso de reflexión en el código y sus dependencias, y puede ser necesario usar anotaciones para ayudar al compilador de AOT nativo a comprender los patrones de reflexión. Cuando el compilador encuentra un patrón de reflexión, no puede analizar estáticamente y, por tanto, no puede compilar la aplicación, genera advertencias de recorte. AOT nativo también le impide usar código dinámico en la aplicación. Por ejemplo, la compilación System.Linq.Expressions no funcionará según lo previsto y no es posible cargar y ejecutar ensamblados en tiempo de ejecución. Cuando el compilador encuentra un patrón dinámico, no puede compilar con antelación, generará una advertencia de AOT.
En la aplicación MAUI de .NET esto significa que:
- Todo XAML debe estar compilado con antelación. Por lo tanto, asegúrate de que no has deshabilitado la compilación XAML y de que se compilan todos los enlaces. Para obtener más información, consulta Compilación XAML y Enlaces compilados.
- Todas las expresiones de enlace deben usar enlaces compilados, en lugar de una ruta de acceso de enlace establecida en una cadena. Para obtener más información, consulta Enlaces compilados.
- Es posible que no se llame a los operadores de conversión implícitos al asignar un valor de un tipo incompatible a una propiedad en XAML o cuando dos propiedades de tipos diferentes usan un enlace de datos. En su lugar, debe definir un TypeConverter para el tipo y adjuntarlo al tipo mediante .TypeConverterAttribute Para obtener más información, vea Definir un TypeConverter para reemplazar un operador de conversión implícito.
- No es posible analizar XAML en tiempo de ejecución con el LoadFromXaml método . Aunque esto se puede hacer seguro mediante la anotación de todos los tipos que se pueden cargar en tiempo de ejecución con el
DynamicallyAccessedMembers
atributo o elDynamicDependency
atributo es muy propenso a errores y no se recomienda. - La recepción de datos de navegación mediante el QueryPropertyAttribute no funcionará. En su lugar, debe implementar la IQueryAttributable interfaz en los tipos que necesitan aceptar parámetros de consulta. Para obtener más información, vea Procesamiento de datos de navegación mediante un único método.
- Es posible que la
SearchHandler.DisplayMemberName
propiedad no funcione. En su lugar, debes proporcionar un ItemTemplate para definir la apariencia de los resultados SearchHandler. Para obtener más información, vea Definir la apariencia del elemento de resultados de búsqueda. - No es posible personalizar la apariencia de la interfaz de usuario con la extensión de marcado XAML
OnPlatform
. En su lugar, debería utilizar la clase OnPlatform<T>. Para obtener más información, consulte Personalizar la apariencia de la interfaz de usuario en función de la plataforma. - No es posible personalizar la apariencia de la interfaz de usuario con la extensión de marcado XAML
OnIdiom
. En su lugar, debe usar la clase OnIdiom<T>. Para obtener más información, consulte Personalizar la apariencia de la interfaz de usuario en función de la expresión del dispositivo.
Importante
El intérprete mono no es compatible con la implementación de AOT nativa y, por tanto, las $(UseInterpreter)
propiedades y $(MtouchInterpreter)
de MSBuild no tienen ningún efecto al usar AOT nativo. Para obtener más información sobre el intérprete mono, consulte Intérprete mono en iOS y Mac Catalyst.
Para obtener más información sobre las advertencias de recorte, consulte Introducción a las advertencias de recorte. Para obtener más información sobre las advertencias de AOT, vea Introducción a las advertencias de AOT.
Adaptación de una aplicación a la implementación de AOT nativa
Use la siguiente lista de comprobación para ayudarle a adaptar la aplicación a los requisitos de implementación de AOT nativos:
- Asegúrese de que todo XAML está compilado:
- Quite todo el
[XamlCompilation(XamlCompilationOptions.Skip)]
uso. - Quite todo el
<?xaml-comp compile="false" ?>
uso.
- Quite todo el
- Quite todas las llamadas al LoadFromXaml método .
- Asegúrese de que se compilan todos los enlaces de datos. Para obtener más información, consulta Enlaces compilados.
- Asegúrese de que todos los enlaces de datos XAML se anotan con
x:DataType
. - Asegúrese de que todos los enlaces de datos de código reemplazan todos los enlaces basados en cadenas por enlaces basados en lambda.
- Asegúrese de que todos los enlaces de datos XAML se anotan con
- Reemplace todo uso de la extensión de marcado XAML
OnPlatform
por una implementación que utilice la clase OnPlatform<T>. Para obtener más información, consulte Personalizar la apariencia de la interfaz de usuario en función de la plataforma. - Reemplace todo uso de la extensión de marcado XAML
OnIdiom
por una implementación que use la clase OnIdiom<T>. Para obtener más información, consulte Personalizar la apariencia de la interfaz de usuario en función de la expresión del dispositivo. - Reemplace todo
[QueryProperty(...)]
el uso por una implementación de laIQueryAttributable
interfaz. Para obtener más información, vea Procesamiento de datos de navegación mediante un único método. - Reemplace todo el
SearchHandler.DisplayMemberName
uso por .ItemTemplate Para obtener más información, vea Definir la apariencia del elemento de resultados de búsqueda. - Reemplace todos los operadores de conversión implícitos para los tipos usados en XAML por un TypeConvertery lo adjunte al tipo mediante TypeConverterAttribute. Para obtener más información, vea Definir un TypeConverter para reemplazar un operador de conversión implícito.
- Al convertir de tipo a tipo
A
, se usará elB
método en un convertidor de tipos asociado aConvertTo
o se usará elA
método en un convertidor de tipos asociado aConvertFrom
.B
- Cuando los tipos de origen y destino tienen un convertidor de tipos asociado, se puede usar cualquiera de ellos.
- Al convertir de tipo a tipo
- Compile todas las expresiones regulares mediante generadores de origen. Para más información, consulte Generadores de código fuente de expresiones regulares de .NET.
- Asegúrese de que la serialización y la deserialización json usan un contexto generado por el origen. Para más información, consulte Api mínimas y cargas JSON.
- Revise y corrija las advertencias de recorte o AOT. Para obtener más información, vea Introducción a las advertencias de recorte e Introducción a las advertencias de AOT.
- Pruebe exhaustivamente la aplicación.
Compatibilidad nativa de diagnóstico de AOT en iOS y Mac Catalyst
AOT nativo y Mono comparten un subconjunto de funcionalidades de diagnóstico e instrumentación. Debido a la gama de herramientas de diagnóstico de Mono, puede ser beneficioso diagnosticar y depurar problemas dentro de Mono en lugar de AOT nativo. Las aplicaciones que son compatibles con AOT y recortadas no deben tener diferencias de comportamiento, por lo que las investigaciones a menudo se aplican a ambos entornos de ejecución.
En la tabla siguiente se muestra la compatibilidad de diagnóstico con AOT nativo en iOS y Mac Catalyst:
Característica | Totalmente compatible | Compatibilidad parcial | No compatible |
---|---|---|---|
Observabilidad y telemetría | Compatibilidad parcial | ||
Diagnósticos en tiempo de desarrollo | Compatibilidad total | ||
Depuración nativa | Compatibilidad parcial | ||
Generación de perfiles de CPU | Compatibilidad parcial | ||
Análisis por montón | No compatible |
En las secciones siguientes se proporciona información adicional sobre esta compatibilidad con diagnósticos.
Observabilidad y telemetría
El seguimiento de aplicaciones .NET MAUI en plataformas móviles está habilitado a través de dotnet-dsrouter que conecta herramientas de diagnóstico con aplicaciones .NET que se ejecutan en iOS y Mac Catalyst, a través de TCP/IP. Sin embargo, AOT nativo no es compatible actualmente con este escenario, ya que no admite componentes EventPipe/DiagnosticServer creados con la pila TCP/IP. La observabilidad sigue siendo factible explícitamente en el código.
Diagnósticos en tiempo de desarrollo
Las herramientas de la CLI de .NET proporcionan comandos independientes para build
y publish
.
dotnet build
(o Start Debugging (F5)
en Visual Studio Code), usa Mono de forma predeterminada al compilar o iniciar aplicaciones .NET MAUI iOS o Mac Catalyst. Solo dotnet publish
creará una aplicación AOT nativa, si este modelo de implementación está habilitado en el archivo del proyecto.
No todas las herramientas de diagnóstico funcionarán sin problemas con las aplicaciones AOT nativas publicadas. Sin embargo, todas las aplicaciones que son recortadas y compatibles con AOT (es decir, las que no producen ninguna advertencia de recorte y AOT en tiempo de compilación) no deben tener diferencias de comportamiento entre Mono y AOT nativo. Por lo tanto, todas las herramientas de diagnóstico en tiempo de desarrollo de .NET, como Recarga activa, siguen estando disponibles para los desarrolladores durante el ciclo de desarrollo de aplicaciones móviles.
Sugerencia
Debe desarrollar, depurar y probar la aplicación como de costumbre y publicar la aplicación final con AOT nativo como uno de los últimos pasos.
Depuración nativa
Al ejecutar la aplicación .NET MAUI iOS o Mac Catalyst durante el desarrollo, se ejecuta en Mono de forma predeterminada. Sin embargo, si la implementación de AOT nativa está habilitada en el archivo del proyecto, se espera que el comportamiento sea el mismo entre Mono y AOT nativo cuando la aplicación no genere ninguna advertencia de recorte y AOT en tiempo de compilación. Siempre que la aplicación cumpla este requisito, puede usar el motor de depuración administrado estándar de Visual Studio Code para desarrollo y pruebas,
Después de la publicación, las aplicaciones AOT nativas son archivos binarios nativos verdaderos, por lo que el depurador administrado no funcionará en ellos. Sin embargo, el compilador AOT nativo genera archivos ejecutables totalmente nativos que puede depurar con lldb
. Depurar una aplicación Mac Catalyst con lldb
es directa, ya que se ejecuta en el mismo sistema. Sin embargo, la depuración de aplicaciones iOS de NativeAOT requiere un esfuerzo adicional.
Depuración de aplicaciones iOS de .NET MAUI con AOT nativo
Las aplicaciones de iOS de .NET MAUI que son compatibles con AOT nativo y que están configuradas y publicadas correctamente con este modelo de implementación, se pueden depurar de la siguiente manera:
Publique la aplicación con el destino
ios-arm64
de AOT nativo y anote la siguiente información:- Nombre de la aplicación (al que se hace referencia a continuación como
<app-name>
). - Identificador de agrupación (al que se hace referencia a continuación como
<bundle-identifier>
). - Ruta de acceso al archivo .ipa de archivo de la aplicación publicada (al que se hace referencia a continuación como
<path-to-ipa>
).
- Nombre de la aplicación (al que se hace referencia a continuación como
Obtenga el identificador de dispositivo físico (al que se hace referencia a continuación como
<device-identifier>
):xcrun devicectl list devices
Instale la aplicación en el dispositivo físico:
xcrun devicectl device install app --device <device-identifier> <path-to-ipa>
Inicie la aplicación en el dispositivo físico:
xcrun devicectl device process launch --device <device-identifier> --start-stopped <bundle-identifier>
Abra
lldb
y conéctese al dispositivo físico:(lldb) device select <device-identifier> (lldb) device process attach -n <app-name>
Después de completar correctamente estos pasos, podrá iniciar la depuración de la aplicación nativa AOT .NET MAUI iOS con lldb
.
Importancia del archivo de símbolos
De forma predeterminada, los símbolos de depuración se quitan del archivo binario de la aplicación en un archivo .dSYM . Los depuradores y las herramientas de análisis post mortem usan este archivo para mostrar información sobre variables locales, números de línea de origen y para volver a crear seguimientos de pila de volcados de memoria. Por lo tanto, es esencial conservar el archivo de símbolos antes de enviar la aplicación a App Store.
Generación de perfiles de CPU
Xcode Instruments se puede usar para recopilar ejemplos de CPU de una aplicación AOT nativa.
Análisis del montón
Actualmente no se admite el análisis del montón con AOT nativo.