Natywne wdrożenie AOT w systemach iOS i Mac Catalyst
Natywne wdrożenie AOT tworzy aplikację interfejsu użytkownika aplikacji wieloplatformowej platformy .NET (.NET MAUI) w systemach iOS i Mac Catalyst, która została skompilowana przed czasem (AOT) do kodu natywnego. Natywna funkcja AOT wykonuje analizę programu statycznego, pełne przycinanie aplikacji, co jest agresywne w usuwaniu kodu, który nie jest statycznie przywoływał, i przed czasem generowania kodu.
Publikowanie i wdrażanie natywnej aplikacji AOT daje następujące korzyści:
- Zmniejszony rozmiar pakietu aplikacji.
- Krótszy czas uruchamiania.
- Krótszy czas kompilacji.
Natywna funkcja AOT wprowadza ograniczenia dotyczące użycia niektórych aspektów środowiska uruchomieniowego platformy .NET i powinny być używane tylko w scenariuszach, w których rozmiar i wydajność aplikacji są ważne. Wymaga to dostosowania aplikacji do natywnych wymagań AOT, co oznacza, że są one w pełni przycinane i zgodne z usługą AOT. Aby uzyskać więcej informacji na temat natywnych ograniczeń AOT, zobacz Natywne ograniczenia AOT.
Po włączeniu wdrożenia natywnego AOT system kompilacji analizuje kod i wszystkie jego zależności, aby sprawdzić, czy jest odpowiedni do pełnego przycinania i kompilacji AOT. W przypadku wykrycia niezgodności generowane są ostrzeżenia dotyczące przycinania i AOT. Jedno przycinanie lub ostrzeżenie AOT oznacza, że aplikacja nie jest zgodna z natywnym wdrożeniem AOT i że może nie działać poprawnie. W związku z tym podczas kompilowania aplikacji dla wdrożenia natywnego AOT należy przejrzeć i poprawić wszystkie ostrzeżenia dotyczące przycinania i AOT. Wykonanie tej czynności może spowodować wyjątki w czasie wykonywania, ponieważ mógł zostać usunięty niezbędny kod. Jeśli pominięto ostrzeżenia, aplikacja wdrożona przez usługę AOT musi być dokładnie przetestowana, aby sprawdzić, czy funkcje nie uległy zmianie z niezatrimmowanej aplikacji. Aby uzyskać więcej informacji, zobacz Introduction to trim warnings (Wprowadzenie do ostrzeżeń dotyczących przycinania) i Introduction to AOT warnings (Wprowadzenie do ostrzeżeń dotyczących funkcji AOT).
Uwaga
Mogą wystąpić przypadki, w których naprawianie przycinania i ostrzeżeń AOT nie jest możliwe, na przykład w przypadku wystąpienia ich w bibliotekach innych firm. W takich przypadkach należy zaktualizować biblioteki innych firm, aby stały się w pełni zgodne.
Natywne korzyści z wydajności usługi AOT
Publikowanie i wdrażanie natywnej aplikacji AOT tworzy aplikację, która zazwyczaj jest mniejsza do 2,5 razy, a aplikacja, która uruchamia się zwykle do 2 razy szybciej. Jednak dokładne korzyści z wydajności zależą od wielu czynników, w tym używanej platformy, urządzenia, na którym działa aplikacja, i samej aplikacji.
Ważne
Na poniższych wykresach przedstawiono typowe korzyści z wydajności wdrożenia natywnego AOT dla dotnet new maui
aplikacji w systemach iOS i Mac Catalyst. Jednak dokładne dane są zależne od sprzętu i mogą ulec zmianie w przyszłych wersjach.
Na poniższym wykresie przedstawiono rozmiar pakietu aplikacji dla dotnet new maui
aplikacji w systemach iOS i Mac Catalyst w różnych modelach wdrażania:
Na powyższym wykresie pokazano, że zazwyczaj natywna funkcja AOT generuje ponad 2 razy mniejsze aplikacje dla systemów iOS i Mac Catalyst w porównaniu z domyślnym modelem wdrażania.
Na poniższym wykresie przedstawiono średni czas uruchamiania na określonym sprzęcie dla dotnet new maui
aplikacji w systemach iOS i Mac Catalyst we wdrożeniu mono i natywnym AOT:
Na powyższym wykresie pokazano, że natywna funkcja AOT zwykle ma do 2 razy szybszy czas uruchamiania na urządzeniach z systemem iOS i 1,2 razy szybszy czas uruchamiania w katalizatorze Mac, w porównaniu z wdrożeniem mono.
Na poniższym wykresie przedstawiono średni czas kompilacji na określonym sprzęcie dla dotnet new maui
aplikacji w systemach iOS i Mac Catalyst w różnych modelach wdrażania:
Na powyższym wykresie pokazano, że zazwyczaj natywna funkcja AOT ma do 2,8 razy szybszy czas kompilacji na urządzeniach z systemem iOS w porównaniu z domyślnym modelem wdrażania. W przypadku programu Mac Catalyst czasy kompilacji są porównywalne dla aplikacji arm64 z pojedynczymi identyfikatorami RID, ale są nieco wolniejsze w przypadku aplikacji uniwersalnych w porównaniu z wdrożeniem mono.
Ważne
W wielu scenariuszach natywna usługa AOT będzie tworzyć mniejsze i szybsze aplikacje. Jednak w niektórych scenariuszach natywna usługa AOT może nie tworzyć mniejszych i szybszych aplikacji. W związku z tym ważne jest przetestowanie i profilowanie aplikacji w celu określenia wyniku włączenia natywnego wdrożenia AOT.
Publikowanie przy użyciu natywnej funkcji AOT
Natywny model wdrażania AOT jest włączony z właściwością $(PublishAot)
kompilacji i poleceniem dotnet publish
. W poniższym przykładzie pokazano, jak zmodyfikować plik projektu w celu włączenia natywnego wdrożenia AOT w systemach iOS i 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>
$(IsAotCompatible)
Ustawienie właściwości build na true
, dla wszystkich platform umożliwia przycinanie i analizatory AOT. Te analizatory ułatwiają identyfikowanie kodu, który nie jest zgodny z przycinaniem lub AOT.
Warunkowe ustawienie $(PublishAot)
na true
, dla systemów iOS i Mac Catalyst umożliwia dynamiczną analizę użycia kodu podczas kompilacji i natywnej kompilacji AOT podczas publikowania. Natywna analiza AOT obejmuje cały kod aplikacji i wszystkie biblioteki, od których zależy aplikacja.
Ostrzeżenie
Właściwość $(PublishAot)
kompilacji nie powinna być warunkowa przez konfigurację kompilacji. Dzieje się tak, ponieważ przełączniki funkcji przycinania są włączone lub wyłączone na podstawie wartości $(PublishAot)
właściwości kompilacji, a te same funkcje powinny być włączone lub wyłączone we wszystkich konfiguracjach kompilacji, aby kod zachowywał się identycznie. Aby uzyskać więcej informacji na temat przycinania przełączników funkcji, zobacz Przycinanie przełączników funkcji.
Jedynym sposobem sprawdzenia, czy natywna aplikacja AOT działa prawidłowo, jest opublikowanie jej przy użyciu i dotnet publish
sprawdzenie, czy nie ma żadnych ostrzeżeń dotyczących przycinania ani AOT generowanych przez kod i jego zależności. W szczególności dotnet build -t:Publish
nie jest równoważne .dotnet publish
Użyj następującego dotnet publish
polecenia, aby opublikować aplikację w systemach iOS i Mac Catalyst przy użyciu natywnego wdrożenia 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
Napiwek
Publikowanie aplikacji często w celu odnajdywania problemów z przycinaniem lub AOT na wczesnym etapie cyklu projektowania.
Ograniczenia natywnej usługi AOT
Natywna funkcja AOT wprowadza ograniczenia dotyczące użycia niektórych aspektów środowiska uruchomieniowego platformy .NET i powinny być używane tylko w scenariuszach, w których rozmiar i wydajność aplikacji są ważne. Wymaga to dostosowania aplikacji do natywnych wymagań AOT, co oznacza, że są one w pełni przycinane i zgodne z usługą AOT, a to może wymagać dużo pracy. Oprócz ograniczeń platformy .NET dotyczących wdrożenia natywnego AOT natywne wdrożenie AOT dla platformy .NET MAUI ma dodatkowe ograniczenia.
Biblioteki innych firm, od których zależą aplikacje, mogą nie być zgodne z usługą AOT. Jedynym sposobem upewnienia się, że biblioteka jest przycinana, a zgodna z usługą AOT jest publikowanie aplikacji przy użyciu natywnego wdrożenia AOT i dotnet publish
polecenia oraz sprawdzenie, czy kompilator natywnej AOT generuje ostrzeżenia dla biblioteki. Aby uzyskać informacje o tworzeniu własnych bibliotek zgodnych z funkcją AOT, zobacz How to make libraries compatible with native AOT (Jak tworzyć biblioteki zgodne z natywną funkcją AOT).
Odbicie i kod dynamiczny
Wdrożenie natywnej funkcji AOT ogranicza użycie odbicia w kodzie i jego zależnościach i może być konieczne użycie adnotacji, aby ułatwić kompilatorowi natywnego AOT zrozumienie wzorców odbicia. Gdy kompilator napotka wzorzec odbicia, nie może statycznie analizować i dlatego nie może skompilować aplikacji, generuje ostrzeżenia dotyczące przycinania. Natywna funkcja AOT uniemożliwia również używanie kodu dynamicznego w aplikacji. Na przykład kompilowanie System.Linq.Expressions nie będzie działać zgodnie z oczekiwaniami i nie można załadować i wykonać zestawów w czasie wykonywania. Gdy kompilator napotka wzorzec dynamiczny, nie może być kompilowany z wyprzedzeniem, spowoduje wygenerowanie ostrzeżenia dotyczącego funkcji AOT.
W aplikacji .NET MAUI oznacza to, że:
- Cały kod XAML musi być skompilowany przed upływem czasu. W związku z tym upewnij się, że kompilacja XAML nie została wyłączona i że wszystkie powiązania są kompilowane. Aby uzyskać więcej informacji, zobacz Kompilacja XAML i Skompilowane powiązania.
- Wszystkie wyrażenia powiązania muszą używać skompilowanych powiązań, a nie ścieżki powiązania ustawionej na ciąg. Aby uzyskać więcej informacji, zobacz Skompilowane powiązania.
- Niejawne operatory konwersji mogą nie być wywoływane podczas przypisywania wartości niezgodnego typu do właściwości w języku XAML lub gdy dwie właściwości różnych typów używają powiązania danych. Zamiast tego należy zdefiniować element TypeConverter dla typu i dołączyć go do typu przy użyciu elementu TypeConverterAttribute. Aby uzyskać więcej informacji, zobacz Define a TypeConverter to replace an implicit conversion operator (Definiowanie operatora konwersji niejawnej).
- Nie można przeanalizować kodu XAML w czasie wykonywania za pomocą LoadFromXaml metody . Chociaż można to zrobić przycinać bezpiecznie, dodając adnotacje do wszystkich typów, które mogą być ładowane w czasie wykonywania z atrybutem
DynamicallyAccessedMembers
lubDynamicDependency
atrybutem jest to bardzo podatne na błędy i nie jest zalecane. - Odbieranie danych nawigacji przy użyciu elementu QueryPropertyAttribute nie będzie działać. Zamiast tego należy zaimplementować IQueryAttributable interfejs dla typów, które muszą akceptować parametry zapytania. Aby uzyskać więcej informacji, zobacz Przetwarzanie danych nawigacji przy użyciu jednej metody.
- Właściwość
SearchHandler.DisplayMemberName
może nie działać. Zamiast tego należy podać element , ItemTemplate aby zdefiniować wygląd SearchHandler wyników. Aby uzyskać więcej informacji, zobacz Definiowanie wyglądu elementu wyników wyszukiwania.
Ważne
Interpreter Mono nie jest zgodny z natywnym wdrożeniem AOT, dlatego $(UseInterpreter)
właściwości i $(MtouchInterpreter)
MSBuild nie mają wpływu podczas korzystania z natywnej AOT. Aby uzyskać więcej informacji na temat interpretera Mono, zobacz Interpreter mono w systemach iOS i Mac Catalyst.
Aby uzyskać więcej informacji na temat ostrzeżeń dotyczących przycinania, zobacz Wprowadzenie do ostrzeżeń dotyczących przycinania. Aby uzyskać więcej informacji na temat ostrzeżeń AOT, zobacz Wprowadzenie do ostrzeżeń AOT.
Dostosowywanie aplikacji do natywnego wdrożenia usługi AOT
Skorzystaj z poniższej listy kontrolnej, aby ułatwić dostosowanie aplikacji do natywnych wymagań dotyczących wdrażania AOT:
- Upewnij się, że cały kod XAML został skompilowany:
- Usuń wszystkie
[XamlCompilation(XamlCompilationOptions.Skip)]
użycie. - Usuń wszystkie
<?xaml-comp compile="false" ?>
użycie.
- Usuń wszystkie
- Usuń wszystkie wywołania LoadFromXaml metody .
- Upewnij się, że wszystkie powiązania danych są kompilowane. Aby uzyskać więcej informacji, zobacz Skompilowane powiązania.
- Upewnij się, że wszystkie powiązania danych XAML są oznaczone adnotacjami .
x:DataType
- Upewnij się, że wszystkie powiązania danych kodu zastępują wszystkie powiązania oparte na ciągach powiązaniami opartymi na lambda.
- Upewnij się, że wszystkie powiązania danych XAML są oznaczone adnotacjami .
- Zastąp wszystkie
[QueryProperty(...)]
użycie implementacją interfejsuIQueryAttributable
. Aby uzyskać więcej informacji, zobacz Przetwarzanie danych nawigacji przy użyciu jednej metody. - Zastąp wszystkie
SearchHandler.DisplayMemberName
użycie elementem ItemTemplate. Aby uzyskać więcej informacji, zobacz Definiowanie wyglądu elementu wyników wyszukiwania. - Zastąp wszystkie niejawne operatory konwersji dla typów używanych w języku XAML elementem TypeConverter, a następnie dołącz go do typu przy użyciu elementu TypeConverterAttribute. Aby uzyskać więcej informacji, zobacz Define a TypeConverter to replace an implicit conversion operator (Definiowanie operatora konwersji niejawnej).
- Podczas konwertowania z typu na typ
B
A
ConvertTo
zostanie użyta metoda w konwerterze typów skojarzonym zA
programem lubConvertFrom
metoda w konwerterze typów skojarzonym zB
programem . - Gdy oba typy źródłowe i docelowe mają skojarzony konwerter typów, można ich użyć.
- Podczas konwertowania z typu na typ
- Skompiluj wszystkie wyrażenia regularne przy użyciu generatorów źródłowych. Aby uzyskać więcej informacji, zobacz Generatory źródeł wyrażeń regularnych platformy .NET.
- Upewnij się, że serializacja i deserializacja JSON używają kontekstu wygenerowanego przez źródło. Aby uzyskać więcej informacji, zobacz Minimalne interfejsy API i ładunki JSON.
- Przejrzyj i popraw wszelkie ostrzeżenia dotyczące przycinania lub AOT. Aby uzyskać więcej informacji, zobacz Introduction to trim warnings (Wprowadzenie do ostrzeżeń dotyczących przycinania) i Introduction to AOT warnings (Wprowadzenie do ostrzeżeń dotyczących funkcji AOT).
- Dokładnie przetestuj aplikację.
Natywna obsługa diagnostyczna AOT w systemach iOS i Mac Catalyst
Natywna funkcja AOT i Mono udostępniają podzbiór możliwości diagnostyki i instrumentacji. Ze względu na szereg narzędzi diagnostycznych mono korzystne może być diagnozowanie i debugowanie problemów w obrębie mono zamiast natywnej AOT. Aplikacje, które są przycinane i zgodne z AOT, nie powinny mieć różnic behawioralnych, więc badania często mają zastosowanie do obu środowisk uruchomieniowych.
W poniższej tabeli przedstawiono obsługę diagnostyki przy użyciu natywnej funkcji AOT w systemach iOS i Mac Catalyst:
Funkcja | W pełni obsługiwane | Zaimportowano częściowo | Nieobsługiwane |
---|---|---|---|
Obserwowanie i telemetria | Częściowo obsługiwane | ||
Diagnostyka czasu programowania | W pełni obsługiwane | ||
Debugowanie natywne | Częściowo obsługiwane | ||
Profilowanie procesora CPU | Częściowo obsługiwane | ||
Analiza stert | Nieobsługiwane |
Poniższe sekcje zawierają dodatkowe informacje o tej obsłudze diagnostycznej.
Obserwowanie i telemetria
Śledzenie aplikacji MAUI platformy .NET na platformach mobilnych jest włączone za pośrednictwem dotnet-dsrouter , który łączy narzędzia diagnostyczne z aplikacjami platformy .NET uruchomionymi w systemach iOS i Mac Catalyst za pośrednictwem protokołu TCP/IP. Jednak natywna funkcja AOT nie jest obecnie zgodna z tym scenariuszem, ponieważ nie obsługuje składników EventPipe/DiagnosticServer utworzonych za pomocą stosu TCP/IP. Możliwość obserwacji jest nadal osiągalna jawnie w kodzie.
Diagnostyka czasu programowania
Narzędzia interfejsu wiersza polecenia platformy .NET udostępnia oddzielne polecenia dla build
i publish
. dotnet build
(lub Start Debugging (F5)
w programie Visual Studio Code) używa rozwiązania Mono domyślnie podczas kompilowania lub uruchamiania aplikacji .NET MAUI dla systemu iOS lub Mac Catalyst. Tylko dotnet publish
utworzy natywną aplikację AOT, jeśli ten model wdrażania jest włączony w pliku projektu.
Nie wszystkie narzędzia diagnostyczne będą bezproblemowo współdziałać z opublikowanymi natywnymi aplikacjami AOT. Jednak wszystkie aplikacje, które są przycinane i zgodne z AOT (czyli te, które nie generują żadnych ostrzeżeń przycinania i AOT w czasie kompilacji) nie powinny mieć różnic behawioralnych między mono i natywną AOT. W związku z tym wszystkie narzędzia diagnostyczne w czasie programowania platformy .NET, takie jak Przeładowywanie na gorąco, są nadal dostępne dla deweloperów podczas cyklu tworzenia aplikacji mobilnych.
Napiwek
Należy opracowywać, debugować i testować aplikację jak zwykle i publikować ostateczną aplikację przy użyciu natywnej usługi AOT jako jednego z ostatnich kroków.
Debugowanie natywne
Po uruchomieniu aplikacji .NET MAUI dla systemu iOS lub Mac Catalyst podczas opracowywania jest domyślnie uruchamiana na platformie Mono. Jeśli jednak wdrożenie natywnej funkcji AOT jest włączone w pliku projektu, zachowanie powinno być takie samo między mono i natywną funkcją AOT, gdy aplikacja nie generuje żadnych ostrzeżeń dotyczących przycinania i AOT w czasie kompilacji. Jeśli aplikacja spełnia to wymaganie, możesz użyć standardowego aparatu debugowania zarządzanego programu Visual Studio Code do programowania i testowania.
Po opublikowaniu natywne aplikacje AOT są prawdziwymi natywnymi plikami binarnymi, więc zarządzany debuger nie będzie na nich działać. Jednak kompilator natywnej AOT generuje w pełni natywne pliki wykonywalne, które można debugować za pomocą polecenia lldb
. Debugowanie aplikacji Mac Catalyst za pomocą lldb
polecenia jest proste, ponieważ jest wykonywane w tym samym systemie. Jednak debugowanie aplikacji NativeAOT dla systemu iOS wymaga dodatkowego nakładu pracy.
Debugowanie aplikacji .NET MAUI dla systemu iOS przy użyciu natywnej funkcji AOT
Aplikacje .NET MAUI dla systemu iOS, które są zgodne z natywną usługą AOT i które są prawidłowo skonfigurowane i opublikowane przy użyciu tego modelu wdrażania, można debugować w następujący sposób:
Opublikuj aplikację przy użyciu natywnej wartości docelowej
ios-arm64
usługi AOT i zanotuj następujące informacje:- Nazwa aplikacji (przywołyni poniżej jako
<app-name>
). - Identyfikator pakietu (przywołyny poniżej jako
<bundle-identifier>
). - Ścieżka do pliku .ipa archiwum opublikowanej aplikacji (przywoływana poniżej jako
<path-to-ipa>
).
- Nazwa aplikacji (przywołyni poniżej jako
Uzyskaj identyfikator urządzenia fizycznego (przywoływny poniżej jako
<device-identifier>
):xcrun devicectl list devices
Zainstaluj aplikację na urządzeniu fizycznym:
xcrun devicectl device install app --device <device-identifier> <path-to-ipa>
Uruchom aplikację na urządzeniu fizycznym:
xcrun devicectl device process launch --device <device-identifier> --start-stopped <bundle-identifier>
Otwórz
lldb
urządzenie fizyczne i połącz się z tym urządzeniem:(lldb) device select <device-identifier> (lldb) device process attach -n <app-name>
Po pomyślnym wykonaniu tych kroków będzie można rozpocząć debugowanie natywnej aplikacji AOT .NET MAUI dla systemu iOS przy użyciu polecenia lldb
.
Znaczenie pliku symboli
Domyślnie symbole debugowania są usuwane z pliku binarnego aplikacji do pliku dSYM . Ten plik jest używany przez debugery i narzędzia analizy pośmiertnej do wyświetlania informacji o zmiennych lokalnych, numerach wierszy źródłowych i ponownego tworzenia śladów stosu zrzutów awaryjnych. W związku z tym należy zachować plik symboli przed przesłaniem aplikacji do sklepu App Store.
Profilowanie procesora CPU
Narzędzia Xcode Instruments mogą służyć do zbierania przykładów procesora CPU natywnej aplikacji AOT.
Analiza stert
Analiza sterty nie jest obecnie obsługiwana w przypadku natywnej funkcji AOT.