Implantação de AOT nativa no iOS e Mac Catalyst

A implantação nativa de AOT gera um aplicativo .NET Multi-platform App UI (.NET MAUI) no iOS e no Mac Catalyst que foi compilado antecipadamente (AOT) para código nativo. O Native AOT realiza análise estática do programa, remoção completa de código desnecessário do seu aplicativo, que remove agressivamente o código que não é referenciado estaticamente, e geração antecipada de código.

A publicação e a implantação de um aplicativo AOT nativo produzem os seguintes benefícios:

  • Tamanho reduzido do pacote do aplicativo.
  • Tempo de inicialização mais rápido.
  • Tempo de construção mais rápido.

O AOT nativo introduzirá limitações no uso de determinados aspectos do runtime do .NET e só deve ser usado em cenários em que o tamanho e o desempenho do aplicativo são importantes. Isso exigirá que você adapte seus aplicativos aos requisitos do Native AOT, o que significa garantir que eles sejam totalmente otimizados e compatíveis com AOT. Para obter mais informações sobre as limitações do AOT nativo, consulte Limitações do AOT nativo.

Quando a implantação nativa de AOT está habilitada, o sistema de compilação analisa seu código e todas as suas dependências para verificar se ele é adequado para a remoção completa de código desnecessário e a compilação AOT. Se forem detectadas incompatibilidades, avisos de remoção de código desnecessário e de AOT serão exibidos. Um único aviso de remoção de código desnecessário ou de AOT significa que o aplicativo não é compatível com a implantação nativa de AOT e que pode não funcionar corretamente. Portanto, ao criar um aplicativo para implantação AOT nativa, você deve revisar e corrigir todos os avisos de truncamento e AOT. Não fazer isso pode resultar em exceções em tempo de execução, pois o código necessário pode ter sido removido. Se você suprimir os avisos, o aplicativo implantado por AOT deverá ser testado minuciosamente para verificar se a funcionalidade não foi alterada em relação ao aplicativo sem truncamento. Para obter mais informações, consulte Introdução aos avisos de trimming e Introdução aos avisos de AOT.

Observação

Pode haver casos em que a correção dos avisos de truncamento e AOT não seja possível, como quando eles ocorrem para bibliotecas de terceiros. Nesses casos, as bibliotecas de terceiros precisarão ser atualizadas para se tornarem totalmente compatíveis.

Benefícios de desempenho nativos do AOT

A publicação e a implantação de um aplicativo AOT nativo produzem um aplicativo que normalmente é até 2,5 vezes menor e um aplicativo que é iniciado normalmente até 2 vezes mais rápido. No entanto, os benefícios exatos de desempenho dependem de vários fatores, que incluem a plataforma que está sendo usada, o dispositivo no qual o aplicativo está sendo executado e o próprio aplicativo.

Importante

Os gráficos a seguir mostram os benefícios típicos de desempenho da implantação do AOT nativo para um dotnet new maui aplicativo no iOS e no Mac Catalyst. No entanto, os dados exatos dependem do hardware e podem ser alterados em versões futuras.

O gráfico a seguir mostra o tamanho do pacote do aplicativo para um dotnet new maui aplicativo no iOS e no Mac Catalyst em diferentes modelos de implantação:

Gráfico mostrando o tamanho do pacote do aplicativo em diferentes modelos de implantação.

O gráfico anterior mostra que, normalmente, o AOT nativo produz aplicativos mais de 2 vezes menores para iOS e Mac Catalyst em comparação com o modelo de implantação padrão.

O gráfico a seguir mostra o tempo médio de inicialização, em hardware específico, para um aplicativo dotnet new maui no iOS e no Mac Catalyst em Mono e implantação AOT nativa:

Gráfico mostrando o tempo médio de inicialização do aplicativo no Mono e no AOT nativo.

O gráfico anterior mostra que o AOT nativo normalmente tem tempos de inicialização até 2x mais rápidos em dispositivos iOS e tempo de inicialização 1,2x mais rápido no Mac Catalyst, em comparação com a implantação do Mono.

O gráfico a seguir mostra o tempo médio de compilação, em hardware específico, para um dotnet new maui aplicativo no iOS e no Mac Catalyst em diferentes modelos de implantação:

Gráfico mostrando o tempo médio de criação do aplicativo no Mono e no AOT nativo.

O gráfico anterior mostra que normalmente o AOT nativo tem tempos de build até 2,8 vezes mais rápidos em dispositivos iOS em comparação com o modelo de implantação padrão. Para o Mac Catalyst, os tempos de compilação são comparáveis para aplicativos arm64 com RID único, mas são ligeiramente mais lentos para aplicativos universais em comparação com a implantação Mono.

Importante

Em muitos cenários, o AOT nativo produzirá aplicativos menores e mais rápidos. No entanto, em alguns cenários, o AOT nativo pode não produzir aplicativos menores e mais rápidos. Portanto, é importante testar e analisar o desempenho do seu aplicativo para determinar o resultado da ativação da implantação AOT nativa.

Publicar usando AOT nativo

O modelo de implantação nativo AOT é habilitado com a propriedade de construção $(PublishAot) e o comando dotnet publish. O exemplo a seguir mostra como modificar um arquivo de projeto para habilitar a implantação AOT nativa no iOS e 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>

Definir a propriedade de compilação $(IsAotCompatible) como true, para todas as plataformas, habilita os analisadores de recorte e AOT. Esses analisadores ajudam a identificar código que não é compatível com trimming nem AOT.

A configuração condicional de $(PublishAot) para true, para iOS e Mac Catalyst, permite a análise do uso de código dinâmico durante a compilação e a compilação AOT nativa durante a publicação. A análise AOT nativa inclui todo o código do aplicativo e todas as bibliotecas das quais o aplicativo depende.

Aviso

A $(PublishAot) propriedade build não deve ser condicionada pela configuração de build. Isso ocorre porque as opções de recursos de recorte são habilitadas ou desabilitadas com base no valor da propriedade de compilação $(PublishAot), e os mesmos recursos devem ser habilitados ou desabilitados em todas as configurações de compilação para que seu código se comporte de maneira idêntica. Para obter mais informações sobre as opções de recursos de recorte, consulte Opções de recursos de recorte.

A única maneira de verificar se um aplicativo Native AOT funciona corretamente é publicá-lo usando dotnet publish e verificar se não há avisos de recorte ou AOT gerados pelo seu código e suas dependências. Em particular, dotnet build -t:Publish não é equivalente a dotnet publish.

Use o seguinte dotnet publish comando para publicar seu aplicativo no iOS e no Mac Catalyst usando a implantação AOT nativa:

# 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

Dica

Publique aplicativos com frequência para detectar problemas de trimming ou AOT logo no início do ciclo de vida de desenvolvimento.

Limitações nativas do AOT

O AOT nativo introduzirá limitações no uso de determinados aspectos do runtime do .NET e só deve ser usado em cenários em que o tamanho e o desempenho do aplicativo são importantes. Isso exigirá que você adapte seus aplicativos aos requisitos do Native AOT — o que significa garantir que eles sejam totalmente compatíveis com *trimming* e AOT —, e isso pode demandar muito trabalho. Além das limitações do .NET relacionadas à implantação do AOT nativo, a implantação do AOT nativo para o .NET MAUI tem limitações adicionais.

As bibliotecas de terceiros das quais seus aplicativos dependem podem não ser compatíveis com AOT. A única maneira de garantir que uma biblioteca seja compatível com trimming e AOT é publicar seu aplicativo usando a implantação Native AOT e o comando dotnet publish e verificar se o compilador Native AOT gera algum aviso para a biblioteca. Para obter informações sobre como tornar suas próprias bibliotecas compatíveis com AOT, consulte Como tornar bibliotecas compatíveis com AOT nativo.

Reflexão e código dinâmico

A implantação do AOT nativo limita o uso de reflexão em seu código e suas dependências, e pode ser necessário usar anotações para ajudar o compilador AOT nativo a entender os padrões de reflexão. Quando o compilador encontra um padrão de reflexão que não consegue analisar estaticamente e, portanto, não consegue compilar o aplicativo, ele gera avisos de trimming. O AOT nativo também impede que você use código dinâmico em seu aplicativo. Por exemplo, a compilação System.Linq.Expressions não funcionará conforme o esperado e não é possível carregar e executar assemblies em runtime. Quando o compilador encontra um padrão dinâmico que não pode compilar antecipadamente, ele produzirá um aviso AOT.

No aplicativo .NET MAUI, isso significa que:

Importante

O interpretador Mono não é compatível com a implantação Native AOT e, portanto, as propriedades $(UseInterpreter) e $(MtouchInterpreter) do MSBuild não têm efeito ao usar o Native AOT. Para obter mais informações, consulte Interpretadores no iOS e Mac Catalyst.

Para obter mais informações sobre avisos de corte, consulte Introdução aos avisos de corte. Para obter mais informações sobre avisos AOT, consulte Introdução aos avisos AOT.

Adaptar um aplicativo à implantação de AOT nativa

Use a lista de verificação a seguir para ajudá-lo a adaptar seu aplicativo aos requisitos de implantação do AOT nativo:

Suporte nativo ao diagnóstico AOT no iOS e Mac Catalyst

AOT e Mono nativos compartilham um subconjunto de recursos de diagnóstico e instrumentação. Devido à variedade de ferramentas de diagnóstico do Mono, pode ser benéfico diagnosticar e depurar problemas no Mono em vez do AOT nativo. Aplicativos compatíveis com trimming e AOT não devem apresentar diferenças de comportamento, portanto, as investigações geralmente se aplicam a ambos os ambientes de execução.

A tabela a seguir mostra o suporte de diagnóstico com AOT nativo no iOS e Mac Catalyst:

Funcionalidade Suporte total Suporte parcial Sem suporte
Observabilidade e telemetria Parcialmente compatível
Diagnósticos durante o desenvolvimento Totalmente suportado
Depuração nativa Parcialmente compatível
Criação de perfil da CPU Parcialmente compatível
Análise de heap Sem suporte

As seções a seguir fornecem informações adicionais sobre esse suporte de diagnóstico.

Observabilidade e telemetria

O rastreamento de aplicativos .NET MAUI em plataformas móveis é habilitado por meio de dotnet-dsrouter , que conecta ferramentas de diagnóstico a aplicativos .NET em execução no iOS e Mac Catalyst, por TCP/IP. No entanto, o Native AOT atualmente não é compatível com esse cenário, pois não oferece suporte aos componentes EventPipe/DiagnosticServer criados com a pilha TCP/IP. A observabilidade ainda pode ser alcançada explicitamente no código.

Diagnóstico durante o desenvolvimento

As ferramentas da CLI do .NET fornecem comandos separados para build e publish. dotnet build (ou Start Debugging (F5) no Visual Studio Code), usa o Mono por padrão ao criar ou iniciar aplicativos .NET MAUI iOS ou Mac Catalyst. Só dotnet publish criará um aplicativo AOT nativo, se esse modelo de implantação estiver habilitado no arquivo de projeto.

Nem todas as ferramentas de diagnóstico funcionarão perfeitamente com aplicativos AOT nativos publicados. No entanto, todos os aplicativos compatíveis com trim e AOT (ou seja, aqueles que não produzem nenhum aviso de trim e AOT no momento da compilação) não devem ter diferenças comportamentais entre o Mono e o AOT nativo. Portanto, todas as ferramentas de diagnóstico de tempo de desenvolvimento do .NET, como Recarga Dinâmica, ainda estão disponíveis para desenvolvedores durante o ciclo de desenvolvimento de aplicativos móveis.

Dica

Você deve desenvolver, depurar e testar seu aplicativo como de costume e publicar seu aplicativo final com AOT nativo como uma das últimas etapas.

Depuração nativa

Quando você executa seu aplicativo .NET MAUI iOS ou Mac Catalyst durante o desenvolvimento, ele é executado no Mono por padrão. Contudo, se a implantação do Native AOT estiver habilitada no arquivo de projeto, espera-se que o comportamento seja o mesmo entre o Mono e o Native AOT quando o aplicativo não estiver gerando avisos de trimming e AOT no momento da compilação. Desde que seu aplicativo atenda a esse requisito, você pode usar o mecanismo de depuração gerenciado padrão do Visual Studio Code para desenvolvimento e teste,

Após a publicação, os aplicativos AOT nativos se tornam binários genuinamente nativos e, portanto, o depurador gerenciado não funcionará neles. No entanto, o compilador AOT nativo gera arquivos totalmente nativos e executáveis que você pode depurar com lldb. Depurar um aplicativo Mac Catalyst com lldb é simples, pois ele é executado no mesmo sistema. No entanto, depurar aplicativos iOS com Native AOT requer esforço adicional.

Depure aplicativos .NET MAUI para iOS com AOT nativo

Aplicações .NET MAUI para iOS compatíveis com Native AOT e que estejam devidamente configuradas e publicadas com este modelo de implantação podem ser depuradas da seguinte forma:

  1. Publique seu aplicativo com segmentação ios-arm64 AOT nativa e observe as seguintes informações:

    • Nome do aplicativo (referenciado abaixo como <app-name>).
    • Identificador de pacote (referenciado abaixo como <bundle-identifier>).
    • Caminho para o arquivo de pacote .ipa do aplicativo publicado (referenciado abaixo como <path-to-ipa>).
  2. Obtenha a ID do seu dispositivo físico (referenciada abaixo como <device-identifier>):

    xcrun devicectl list devices
    
  3. Instale o aplicativo em seu dispositivo físico:

    xcrun devicectl device install app --device <device-identifier> <path-to-ipa>
    
  4. Inicie o aplicativo em seu dispositivo físico:

    xcrun devicectl device process launch --device <device-identifier> --start-stopped <bundle-identifier>
    
  5. Abra lldb e conecte-se ao seu dispositivo físico:

    (lldb) device select <device-identifier>
    (lldb) device process attach -n <app-name>
    

Após concluir com sucesso estas etapas, você poderá iniciar a depuração do seu aplicativo Native AOT .NET MAUI para iOS com lldb.

Importância do arquivo de símbolo

Por padrão, os símbolos de depuração são removidos do arquivo binário do aplicativo para um arquivo .dSYM . Este arquivo é usado por depuradores e ferramentas de análise pós-mortem para exibir informações sobre variáveis ​​locais, números de linha do código-fonte e para recriar rastreamentos de pilha de despejos de memória. Portanto, é essencial preservar o arquivo de símbolo antes de enviar sua inscrição para a App Store.

Criação de perfil da CPU

O Xcode Instruments pode ser usado para coletar amostras de CPU de um aplicativo AOT nativo.

Análise de heap

No momento, a análise de heap não é suportada com o Native AOT.

Confira também