Kompilacja ReadyToRun

Czas uruchamiania i opóźnienie aplikacji platformy .NET można poprawić, kompilując zestawy aplikacji jako format ReadyToRun (R2R). R2R jest formą kompilacji przed czasem (AOT).

Pliki binarne R2R zwiększają wydajność uruchamiania, zmniejszając ilość pracy kompilatora just in time (JIT), który musi wykonywać w miarę ładowania aplikacji. Pliki binarne zawierają podobny kod natywny w porównaniu z tym, co wygenerowałby JIT. Jednak pliki binarne R2R są większe, ponieważ zawierają zarówno kod języka pośredniego (IL), który jest nadal potrzebny w niektórych scenariuszach, oraz natywną wersję tego samego kodu. R2R jest dostępny tylko w przypadku publikowania aplikacji przeznaczonej dla określonych środowisk uruchomieniowych (RID), takich jak Linux x64 lub Windows x64.

Aby skompilować projekt jako ReadyToRun, aplikacja musi zostać opublikowana z właściwością PublishReadyToRun ustawioną na truewartość .

Istnieją dwa sposoby publikowania aplikacji jako ReadyToRun:

  1. Określ flagę PublishReadyToRun bezpośrednio do polecenia dotnet publish. Aby uzyskać szczegółowe informacje, zobacz dotnet publish (Publikowanie w witrynie dotnet ).

    dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=true
    
  2. Określ właściwość w projekcie.

    • <PublishReadyToRun> Dodaj ustawienie do projektu.
    <PropertyGroup>
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    
    • Publikowanie aplikacji bez żadnych parametrów specjalnych.
    dotnet publish -c Release -r win-x64
    

Wpływ korzystania z funkcji ReadyToRun

Kompilacja przed upływem czasu ma złożony wpływ na wydajność aplikacji, co może być trudne do przewidzenia. Ogólnie rzecz biorąc, rozmiar zestawu wzrośnie do przedziału od dwóch do trzech razy większych. Ten wzrost fizycznego rozmiaru pliku może zmniejszyć wydajność ładowania zestawu z dysku i zwiększyć zestaw roboczy procesu. Jednak w zamian liczba metod skompilowanych w czasie wykonywania jest zwykle znacznie zmniejszona. Wynika to z tego, że większość aplikacji, które mają duże ilości kodu, otrzymuje duże korzyści z wydajności dzięki włączeniu funkcji ReadyToRun. Aplikacje, które mają niewielką ilość kodu, prawdopodobnie nie będą miały znaczącej poprawy od włączenia funkcji ReadyToRun, ponieważ biblioteki środowiska uruchomieniowego platformy .NET zostały już wstępnie skompilowane za pomocą funkcji ReadyToRun.

Omówiona tutaj poprawa uruchamiania ma zastosowanie nie tylko do uruchamiania aplikacji, ale także do pierwszego użycia dowolnego kodu w aplikacji. Na przykład Funkcja ReadyToRun może służyć do zmniejszenia opóźnienia odpowiedzi pierwszego użycia internetowego interfejsu API w aplikacji ASP.NET.

Interakcja z kompilacją warstwową

Kod wygenerowany z wyprzedzeniem nie jest tak wysoce zoptymalizowany, jak kod generowany przez JIT. Aby rozwiązać ten problem, kompilacja warstwowa zastąpi powszechnie używane metody ReadyToRun metodami wygenerowanymi przez JIT.

W jaki sposób wybrano zestaw wstępnie skompilowanych zestawów?

Zestaw SDK będzie wstępnie skompilować zestawy, które są dystrybuowane z aplikacją. W przypadku aplikacji samodzielnej ten zestaw zestawów będzie zawierać platformę. Pliki binarne języka C++/CLI nie kwalifikują się do kompilacji ReadyToRun.

Aby wykluczyć określone zestawy z przetwarzania ReadyToRun, użyj <PublishReadyToRunExclude> listy.

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

W jaki sposób zestaw metod do wstępnego kompilowania jest wybierany?

Kompilator spróbuje wstępnie skompilować dowolną liczbę metod. Jednak z różnych powodów nie oczekuje się, że użycie funkcji ReadyToRun uniemożliwi wykonywanie JIT. Takie przyczyny mogą obejmować, ale nie są ograniczone do:

  • Używanie typów ogólnych zdefiniowanych w osobnych zestawach.
  • Współdziałanie z kodem natywnym.
  • Korzystanie ze sprzętowych elementów wewnętrznych, których kompilator nie może udowodnić, jest bezpieczne do użycia na maszynie docelowej.
  • Niektóre nietypowe wzorce IL.
  • Tworzenie metody dynamicznej za pomocą odbicia lub LINQ.

Generowanie symboli do użycia z profilerami

Podczas kompilowania aplikacji przy użyciu funkcji ReadyToRun profileery mogą wymagać symboli do badania wygenerowanych plików ReadyToRun. Aby włączyć generowanie symboli <PublishReadyToRunEmitSymbols> , określ właściwość .

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

Te symbole zostaną umieszczone w katalogu publikowania, a w systemie Windows będzie miało rozszerzenie pliku .ni.pdb, a w przypadku systemu Linux będzie miało rozszerzenie pliku r2rmap. Te pliki nie są zazwyczaj redystrybuowane dla klientów końcowych, ale zazwyczaj będą przechowywane na serwerze symboli. Ogólnie rzecz biorąc, te symbole są przydatne do debugowania problemów z wydajnością związanych z uruchamianiem aplikacji, ponieważ kompilacja warstwowa zastąpi wygenerowany kod ReadyToRun dynamicznie wygenerowanym kodem. Jednak w przypadku próby profilowania aplikacji, która wyłącza kompilację warstwową , symbole będą przydatne.

Gotowe do uruchomienia złożonego

Kompilacja Normal ReadyToRun generuje pliki binarne, które można obsługiwać i manipulować pojedynczo. Począwszy od platformy .NET 6, dodano obsługę kompilacji Composite ReadyToRun. Composite ReadyToRun kompiluje zestaw zestawów, które muszą być dystrybuowane razem. Ma to przewagę nad tym, że kompilator może wykonywać lepsze optymalizacje i zmniejsza zestaw metod, których nie można skompilować za pośrednictwem procesu ReadyToRun. Jednak w miarę kompromisu szybkość kompilacji znacznie się zmniejsza, a ogólny rozmiar pliku aplikacji jest znacznie zwiększony. Ze względu na te kompromisy użycie funkcji Composite ReadyToRun jest zalecane tylko w przypadku aplikacji, które wyłączają kompilację warstwową lub aplikacje działające w systemie Linux, które szukają najlepszego czasu uruchamiania z własnym wdrożeniem. Aby włączyć złożoną kompilację <PublishReadyToRunComposite> ReadyToRun, określ właściwość .

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

Uwaga

Na platformie .NET 6 funkcja Composite ReadyToRun jest obsługiwana tylko w przypadku wdrożenia samodzielnego .

Ograniczenia międzyplatformowe/architektury

W przypadku niektórych platform zestawu SDK kompilator ReadyToRun może kompilować krzyżowo dla innych platform docelowych.

Obsługiwane cele kompilacji opisano w poniższej tabeli podczas określania wartości docelowej dla platformy .NET 6 i nowszych wersji.

Platforma zestawu SDK Obsługiwane platformy docelowe
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)

Obsługiwane cele kompilacji opisano w poniższej tabeli podczas określania wartości docelowej dla platformy .NET 5 i poniżej.

Platforma zestawu SDK Obsługiwane platformy docelowe
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