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ć podczas ładowania aplikacji. Pliki binarne zawierają podobny kod macierzysty w porównaniu z elementem JIT, który mógłby wygenerować. 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 podczas 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 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>
    
    • Opublikuj aplikację bez żadnych specjalnych parametrów.
    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 między dwoma do trzech razy większy. Ten wzrost rozmiaru fizycznego 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 z włączenia funkcji ReadyToRun. Aplikacje, które mają niewielkie ilości kodu, prawdopodobnie nie będą miały znaczącej poprawy w zakresie włączania funkcji ReadyToRun, ponieważ biblioteki środowiska uruchomieniowego platformy .NET zostały już wstępnie skompilowane z funkcją ReadyToRun.

Omówione tutaj ulepszenia uruchamiania dotyczą nie tylko 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 w trybie JIT.

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

Zestaw SDK będzie wstępnie kompilować zestawy, które są dystrybuowane z aplikacją. W przypadku aplikacji samodzielnie ten zestaw zestawów będzie zawierać strukturę. 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>

Jaki jest zestaw metod do wstępnego kompilowania?

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 trybu JIT. Takie przyczyny mogą obejmować, ale nie są ograniczone do następujących:

  • Używanie typów ogólnych zdefiniowanych w osobnych zestawach.
  • Współdziałanie z kodem natywnym.
  • Korzystanie z funkcji wewnętrznych sprzętu, których kompilator nie może udowodnić, jest bezpieczne do użycia na maszynie docelowej.
  • Niektóre niezwykłe wzorce IL.
  • Dynamiczne tworzenie metody za pośrednictwem odbicia lub LINQ.

Generowanie symboli do użycia z profilerami

Podczas kompilowania aplikacji przy użyciu funkcji ReadyToRun profileery mogą wymagać symboli do zbadania 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 dystrybuowane do klientów końcowych, ale zazwyczaj są przechowywane na serwerze symboli. Ogólnie rzecz biorąc, te symbole są przydatne w przypadku debugowania problemów z wydajnością związanych z uruchamianiem aplikacji, ponieważ kompilacja warstwowa zastąpi wygenerowany kod ReadyToRun dynamicznie wygenerowanym kodem. Jeśli jednak próbujesz profilować aplikację, która wyłącza kompilację warstwową, symbole będą przydatne.

Gotowe do uruchomienia złożonego

Kompilacja Normal ReadyToRun tworzy pliki binarne, które można obsługiwać i manipulować pojedynczo. Począwszy od platformy .NET 6, dodano obsługę kompilacji Composite ReadyToRun. Funkcja Composite ReadyToRun kompiluje zestawy, 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ększany. 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 uruchomione w systemie Linux, które szukają najlepszego czasu uruchamiania w przypadku wdrożenia samodzielnego . 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 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