Compartilhar via


Compilação ReadyToRun

A latência e o tempo de inicialização do aplicativo .NET podem ser aprimorados compilando seus assemblies de aplicativo como formato R2R (ReadyToRun). R2R é uma forma de compilação antecipada (AOT).

Os binários R2R melhoram o desempenho de inicialização reduzindo a quantidade de trabalho que o compilador just-in-time (JIT) precisa fazer à medida que seu aplicativo é carregado. Os binários contêm código nativo similar comparado ao que o JIT produziria. Entretanto, os binários R2R são maiores porque contêm código de IL (linguagem intermediária), que ainda é necessário para alguns cenários, e a versão nativa do mesmo código. O R2R só está disponível quando você publica um aplicativo destinado a RID (ambientes de runtime específicos), como Linux x64 ou Windows x64.

Para compilar seu projeto como ReadyToRun, o aplicativo deve ser publicado com a propriedade PublishReadyToRun definida como true.

Há duas maneiras de publicar seu aplicativo como ReadyToRun:

  1. Especifique o flag PublishReadyToRun diretamente no comando dotnet publish. Consulte dotnet publish para obter detalhes.

    dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=true
    
  2. Especificar a propriedade no projeto.

    • Adicione a <PublishReadyToRun> configuração ao seu projeto.
    <PropertyGroup>
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    
    • Publique o aplicativo sem parâmetros especiais.
    dotnet publish -c Release -r win-x64
    

Impacto do uso do recurso ReadyToRun

A compilação antecipada tem um impacto complexo no desempenho do aplicativo, o que pode ser difícil de prever. Em geral, o tamanho de um conjunto aumentará para duas a três vezes o tamanho original. Esse aumento no tamanho físico do arquivo pode reduzir o desempenho do carregamento do assembly do disco e aumentar o conjunto de trabalho do processo. No entanto, em troca, o número de métodos compilados em tempo de execução normalmente é reduzido substancialmente. O resultado é que a maioria dos aplicativos que têm grandes quantidades de código recebe grandes benefícios de desempenho ao habilitar ReadyToRun. Aplicativos que têm pequenas quantidades de código provavelmente não experimentarão uma melhoria significativa ao habilitar ReadyToRun, já que as bibliotecas de runtime do .NET já foram pré-compiladas com ReadyToRun.

O aprimoramento de inicialização discutido aqui se aplica não apenas à inicialização do aplicativo, mas também ao primeiro uso de qualquer código no aplicativo. Por exemplo, ReadyToRun pode ser usado para reduzir a latência de resposta do primeiro uso da API Web em um aplicativo ASP.NET.

Interação com compilação em camadas

O código gerado antecipadamente não é tão otimizado quanto o código produzido pelo JIT. Para resolver esse problema, a compilação em camadas substituirá os métodos ReadyToRun comumente usados por métodos gerados por JIT.

Como o conjunto de assemblies pré-compilados é escolhido?

O SDK pré-compilará os assemblies que são distribuídos com o aplicativo. Para aplicativos autossuficientes, esse conjunto de assemblies incluirá a estrutura. Os binários C++/CLI não são qualificados para compilação ReadyToRun.

Para excluir assemblies específicos do processamento de ReadyToRun, use a lista <PublishReadyToRunExclude>.

<ItemGroup>
  <PublishReadyToRunExclude Include="Contoso.Example.dll" />
</ItemGroup>

Como é escolhido o conjunto de métodos a serem pré-compilados?

O compilador tentará pré-compilar o máximo de métodos possível. No entanto, por vários motivos, não é esperado que o uso do recurso ReadyToRun impeça a execução do JIT. Esses motivos podem incluir, mas não se limitam a:

  • Uso de tipos genéricos definidos em conjuntos separados.
  • Interoperabilidade com código nativo.
  • O uso de intrínsecos de hardware que o compilador não pode provar que sejam seguros de usar em uma máquina-alvo.
  • Certos padrões de IL incomuns.
  • Criação de método dinâmico por meio de reflexão ou LINQ.

Geração de símbolos para uso com criadores de perfil

Ao compilar um aplicativo com ReadyToRun, os criadores de perfil podem exigir símbolos para examinar os arquivos ReadyToRun gerados. Para habilitar a geração de símbolos, especifique a <PublishReadyToRunEmitSymbols> propriedade.

<PropertyGroup>
  <PublishReadyToRunEmitSymbols>true</PublishReadyToRunEmitSymbols>
</PropertyGroup>

Esses símbolos serão colocados no diretório de publicação e para Windows terão uma extensão de arquivo de .ni.pdb e, para Linux, haverá uma extensão de arquivo .r2rmap. Esses arquivos geralmente não são redistribuídos para clientes finais, mas normalmente seriam armazenados em um servidor de símbolos. Em geral, esses símbolos são úteis para depurar problemas de desempenho relacionados à inicialização de aplicativos, pois a compilação em camadas substituirá o código gerado ReadyToRun por código gerado dinamicamente. No entanto, em caso de tentativa de criar o perfil de um aplicativo que desabilite a compilação em camadas, os símbolos serão úteis.

ReadyToRun composto

A compilação Normal ReadyToRun produz binários que podem ser atendidos e manipulados individualmente. Do .NET 6 em diante, o suporte para a compilação de ReadyToRun composta foi adicionado. O ReadyToRun composto compila um conjunto de assemblies que precisam ser distribuídos juntos. Isso tem a vantagem de que o compilador é capaz de executar otimizações melhores e reduz o conjunto de métodos que não podem ser compilados por meio do processo ReadyToRun. No entanto, como uma compensação, a velocidade de compilação é significativamente reduzida e o tamanho geral do arquivo do aplicativo é significativamente aumentado. Devido a essas desvantagens, o uso de ReadyToRun composto só é recomendado para aplicativos que desabilitam a compilação em camadas ou aplicativos em execução no Linux que buscam o melhor tempo de inicialização com uma implantação autossuficiente. Para habilitar a compilação ReadyToRun composta, especifique a <PublishReadyToRunComposite> propriedade.

<PropertyGroup>
  <PublishReadyToRunComposite>true</PublishReadyToRunComposite>
</PropertyGroup>

Observação

No .NET 6, o "Composite ReadyToRun" só tem suporte para implantação independente.

Restrições de plataforma cruzada/arquitetura

Para algumas plataformas de SDK, o compilador ReadyToRun pode fazer a compilação entre outras plataformas de destino.

Os destinos de compilação com suporte são descritos na tabela abaixo para direcionamento ao .NET 6 e a versões posteriores.

Plataforma do SDK Plataformas de destino com suporte
Windows X64 Windows (X86, X64, Arm64), Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
Windows X86 Windows (X86), Linux (Arm32)
Linux X64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
Linux Arm32 Linux Arm32
Linux Arm64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
macOS X64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
macOS Arm64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)

Os destinos de compilação com suporte são descritos na tabela abaixo para direcionamento ao .NET 5 e abaixo.

Plataforma do SDK Plataformas de destino com suporte
Windows X64 Windows X86, Windows X64, Windows Arm64
Windows X86 Windows X86, Windows Arm32
Linux X64 Linux X86, Linux X64, Linux Arm32, Linux Arm64
Linux Arm32 Linux Arm32
Linux Arm64 Linux Arm64
macOS X64 macOS X64