Udostępnij przez


Najlepsze rozwiązania dotyczące wydajności uruchamiania aplikacji

Tworzenie aplikacji platformy uniwersalnej systemu Windows (UWP) z optymalnym czasem uruchamiania przez poprawę sposobu obsługi uruchamiania i aktywacji.

Najlepsze rozwiązania dotyczące wydajności uruchamiania aplikacji

Po części użytkownicy postrzegają, czy aplikacja jest szybka, czy powolna, na podstawie tego, jak długo trwa uruchamianie. Na potrzeby tego tematu czas uruchamiania aplikacji rozpoczyna się, gdy użytkownik uruchamia aplikację, i kończy się, gdy użytkownik może w jakiś sposób wchodzić w interakcję z aplikacją. Ta sekcja zawiera sugestie dotyczące uzyskiwania lepszej wydajności z aplikacji po jej uruchomieniu.

Mierzenie czasu uruchamiania aplikacji

Pamiętaj, aby uruchomić aplikację kilka razy, zanim faktycznie zmierzysz jej czas uruchamiania. Zapewnia to punkt odniesienia dla pomiaru i gwarantuje, że mierzony czas uruchamiania jest możliwie jak najkrótszy.

Po zainstalowaniu aplikacji UWP na komputerach klientów, aplikacja została skompilowana przy użyciu narzędzi łańcucha platformy .NET Native. .NET Native to technologia kompilacji przed czasem, która konwertuje MSIL na natywnie uruchamiany kod maszynowy. Aplikacje .NET Native uruchamiają się szybciej, używają mniejszej ilości pamięci i używają mniejszej ilości baterii niż ich odpowiedniki MSIL. Aplikacje utworzone za pomocą .NET Native są statycznie połączone z niestandardowym środowiskiem uruchomieniowym oraz nową zbieżną platformą .NET Core, która może działać na wszystkich urządzeniach, więc nie zależą od wbudowanej implementacji platformy .NET. Na maszynie deweloperskiej aplikacja domyślnie używa platformy .NET Native, jeśli tworzysz ją w trybie "Release", i używa CoreCLR, jeśli tworzysz ją w trybie "Debug". Można to skonfigurować w programie Visual Studio na stronie Kompilacja w sekcji "Właściwości" (C#) lub na stronie Kompilowanie —>Zaawansowane w sekcji "Mój projekt" (VB). Wyszukaj pole wyboru "Kompiluj przy użyciu łańcucha narzędzi platformy .NET Native".

Oczywiście należy wykonać pomiary, które są reprezentatywne dla użytkownika końcowego. Jeśli więc nie masz pewności, że kompilujesz aplikację do kodu natywnego na maszynie dewelopera, możesz uruchomić narzędzie Native Image Generator (Ngen.exe), aby wstępnie skompilować aplikację przed pomiarem czasu uruchomienia.

W poniższej procedurze opisano sposób uruchamiania Ngen.exe w celu wstępnego kompilowania aplikacji.

Aby uruchomić Ngen.exe

  1. Uruchom aplikację co najmniej raz, aby upewnić się, że Ngen.exe ją wykryje.

  2. Otwórz Harmonogram zadań, wykonując jedną z następujących operacji:

    • Wyszukaj "Harmonogram zadań" na ekranie startowym.
    • Uruchom "taskschd.msc".
  3. W lewym okienku harmonogramu zadańrozwiń bibliotekę harmonogramu zadań.

  4. Rozwiń Microsoft.

  5. Rozwiń Windows.

  6. Wybierz .NET Framework.

  7. Wybierz .NET Framework NGEN 4.x z listy zadań.

    Jeśli używasz komputera 64-bitowego, istnieje również .NET Framework NGEN w wersji 4.x 64. Jeśli tworzysz 64-bitową aplikację, wybierz pozycję .NET Framework NGEN w wersji 4.x 64.

  8. W menu Akcja kliknij na Uruchom.

Ngen.exe prekompiluje wszystkie aplikacje na maszynie, które były używane i nie mają obrazów natywnych. Jeśli istnieje wiele aplikacji, które muszą być wstępnie skompilowane, może to zająć dużo czasu, ale kolejne uruchomienia są znacznie szybsze.

Gdy ponownie skompilujesz aplikację, obraz natywny nie jest już używany. Zamiast tego aplikacja jest kompilowana w czasie rzeczywistym, co oznacza, że jest kompilowana podczas działania aplikacji. Aby uzyskać nowy obraz natywny, należy ponownie uruchomić Ngen.exe.

Odrocz pracę tak długo, jak to możliwe

Aby poprawić czas uruchamiania aplikacji, wykonaj tylko pracę, która absolutnie musi zostać wykonana, aby umożliwić użytkownikowi rozpoczęcie interakcji z aplikacją. Może to być szczególnie korzystne, jeśli można opóźnić ładowanie dodatkowych zestawów. Środowisko uruchomieniowe języka wspólnego ładuje zestaw, gdy jest używany po raz pierwszy. Jeśli możesz zminimalizować liczbę załadowanych zestawów, możesz poprawić czas uruchamiania aplikacji i zużycie pamięci.

Wykonywanie długotrwałej pracy niezależnie

Aplikacja może być interaktywna, mimo że istnieją części aplikacji, które nie są w pełni funkcjonalne. Jeśli na przykład aplikacja wyświetla dane, które trzeba trochę czasu pobrać, możesz wykonać ten kod niezależnie od kodu uruchamiania aplikacji, pobierając dane asynchronicznie. Gdy dane są dostępne, wypełnij interfejs użytkownika aplikacji danymi.

Wiele interfejsów API platformy uniwersalnej systemu Windows (UWP), które pobierają dane, są asynchroniczne, więc prawdopodobnie dane będą pobierane asynchronicznie. Aby uzyskać więcej informacji na temat asynchronicznych interfejsów API, zobacz Wywoływanie asynchronicznych interfejsów API w języku C# lub Visual Basic. Jeśli wykonujesz pracę, która nie korzysta z asynchronicznych interfejsów API, możesz użyć klasy Task do wykonywania długotrwałych zadań, aby nie blokować użytkownika przed interakcją z aplikacją. Dzięki temu aplikacja będzie reagować na użytkownika podczas ładowania danych.

Jeśli ładowanie części interfejsu użytkownika przez aplikację zajmuje wyjątkowo dużo czasu, zastanów się nad dodaniem frazy w tym obszarze, takiej jak "Pobieranie najnowszych danych", aby użytkownicy wiedzieli, że aplikacja nadal przetwarza.

Minimalizuj czas uruchamiania

Wszystkie, ale najprostsze aplikacje wymagają możliwego czasu na załadowanie zasobów, przeanalizowanie kodu XAML, skonfigurowanie struktur danych i uruchomienie logiki podczas aktywacji. W tym miejscu analizujemy proces aktywacji, dzieląc go na trzy fazy. Udostępniamy również wskazówki dotyczące skrócenia czasu spędzonego w każdej fazie i technik tworzenia każdej fazy uruchamiania aplikacji bardziej smaczne dla użytkownika.

Okres aktywacji to czas między momentem uruchomienia aplikacji przez użytkownika a momentem, w którym aplikacja jest funkcjonalna. Jest to krytyczny czas, ponieważ jest to pierwsze wrażenie użytkownika aplikacji. Oczekują natychmiastowej i ciągłej informacji zwrotnej od systemu i aplikacji. System i aplikacja są postrzegane jako uszkodzone lub źle zaprojektowane, gdy aplikacje nie zaczynają się szybko. Co gorsza, jeśli aktywacja aplikacji trwa zbyt długo, menedżer okresu istnienia procesu (PLM) może go zabić lub użytkownik może go odinstalować.

Wprowadzenie do etapów uruchamiania

Uruchomienie obejmuje wiele ruchomych elementów, a wszystkie z nich muszą być prawidłowo zsynchronizowane dla najlepszego doświadczenia użytkownika. Poniższe kroki zachodzą między kliknięciem kafelka aplikacji a wyświetleniem jej zawartości.

  • Powłoka systemu Windows uruchamia proces i wywołuje funkcję Main.
  • Obiekt Application jest tworzony.
    • (Szablon projektu) Konstruktor wywołuje metodę InitializeComponent, co powoduje analizowanie pliku App.xaml i tworzenie obiektów.
  • Zdarzenie Application.OnLaunched zostało zgłoszone.
    • (ProjectTemplate) Kod aplikacji tworzy ramkę i przechodzi do strony MainPage.
    • (ProjectTemplate) Konstruktor mainpage wywołuje InitializeComponent, co powoduje analizowanie pliku MainPage.xaml i tworzenie obiektów.
    • Metoda Window.ProjectTemplate.Current.Activate() jest wywoływana.
  • Platforma XAML uruchamia proces układu, w tym Measure & Arrange.
    • Metoda ApplyTemplate spowoduje utworzenie zawartości szablonu kontrolki dla każdej kontrolki, co zazwyczaj stanowi większość czasu poświęconego na układ podczas uruchamiania.
  • Renderowanie jest wywoływane w celu utworzenia wizualizacji dla całej zawartości okna.
  • Ramka jest przedstawiana Menedżerowi okien pulpitu (DWM).

Rób mniej na swojej drodze do sukcesu w startupie

Zachowaj ścieżkę kodu uruchamiania uwolnioną od wszystkiego, co nie jest potrzebne dla pierwszej klatki.

  • Jeśli masz biblioteki DLL użytkownika zawierające kontrolki, które nie są potrzebne podczas pierwszej klatki, rozważ ich opóźnione ładowanie.
  • Jeśli masz część interfejsu użytkownika zależną od danych z chmury, podziel ten interfejs użytkownika. Najpierw otwórz interfejs użytkownika, który nie jest zależny od chmury, a następnie asynchronicznie wyświetl ten zależny od chmury. Należy również rozważyć buforowanie danych lokalnie, aby aplikacja działała w trybie offline lub nie będzie miała wpływu na powolną łączność sieciową.
  • Pokaż informację o postępie, jeśli interfejs użytkownika czeka na dane.
  • Należy zachować ostrożność w projektach aplikacji obejmujących wiele analiz plików konfiguracji lub interfejsu użytkownika, który jest dynamicznie generowany przez kod.

Zmniejsz liczbę elementów

Wydajność uruchamiania w aplikacji XAML jest bezpośrednio skorelowana z liczbą elementów tworzonych podczas uruchamiania. Mniejsza liczba utworzonych elementów, tym krótszy czas uruchamiania aplikacji. Jako przybliżony punkt odniesienia można uznać, że utworzenie każdego elementu zajmuje 1 ms.

  • Szablony używane w kontrolkach elementów mogą mieć największy wpływ, ponieważ są one powtarzane wielokrotnie. Sprawdź optymalizację interfejsu użytkownika dla ListView i GridView .
  • Kontrolki UserControls i szablony kontrolek zostaną rozwinięte, dlatego należy je również wziąć pod uwagę.
  • Jeśli tworzysz jakikolwiek kod XAML, który nie jest wyświetlany na ekranie, należy uzasadnić, czy podczas uruchamiania należy utworzyć te fragmenty kodu XAML.

W oknie Visual Studio Live Visual Tree przedstawiono liczbę elementów podrzędnych dla każdego węzła w drzewie.

dynamiczne drzewo wizualne.

Użyj odroczenia. Zwijanie elementu lub ustawienie nieprzezroczystości na 0 nie uniemożliwi utworzenia elementu. Za pomocą polecenia x:Load lub x:DeferLoadStrategy możesz opóźnić ładowanie fragmentu interfejsu użytkownika i załadować go w razie potrzeby. Jest to dobry sposób na opóźnienie przetwarzania interfejsu użytkownika, który nie jest widoczny podczas ekranu startowego, dzięki czemu można załadować go w razie potrzeby lub w ramach zestawu logiki opóźniającej. Aby wyzwolić ładowanie, musisz jedynie wywołać FindName dla elementu. Aby uzyskać przykład i więcej informacji, zobacz atrybut x:Load oraz atrybut x:DeferLoadStrategy.

Wirtualizacja. Jeśli masz listę lub zawartość powtarzającą w interfejsie użytkownika, zdecydowanie zaleca się korzystanie z wirtualizacji interfejsu użytkownika. Jeśli interfejs użytkownika listy nie jest zwirtualizowany, płacisz koszt tworzenia wszystkich elementów z góry i może to spowolnić uruchamianie. Sprawdź optymalizację interfejsu użytkownika dla ListView i GridView .

Wydajność aplikacji nie dotyczy tylko nieprzetworzonej wydajności, ale także percepcji. Zmiana kolejności operacji w taki sposób, aby aspekty wizualne miały miejsce najpierw, często sprawia, że użytkownik czuje się jak aplikacja jest szybsza. Użytkownicy będą uważać aplikację za załadowaną, gdy zawartość pojawi się na ekranie. Często aplikacje muszą wykonywać wiele czynności w ramach uruchamiania, a nie wszystkie są wymagane do wywołania interfejsu użytkownika, więc należy je opóźnić lub nadać niższy priorytet niż interfejsowi użytkownika.

W tym temacie omówiono "pierwszą ramkę", która pochodzi z animacji/telewizji i jest miarą czasu, jaki upływa do momentu, gdy zawartość staje się widoczna dla końcowego użytkownika.

Ulepszanie percepcji startupów

Użyjmy przykładu prostej gry online, aby zidentyfikować każdą fazę uruchamiania i różne techniki, aby przekazać opinię użytkownika w całym procesie. W tym przykładzie pierwsza faza aktywacji to czas między naciśnięciem kafelka gry a rozpoczęciem uruchamiania kodu przez użytkownika. W tym czasie system nie ma żadnej zawartości do wyświetlenia użytkownikowi, aby nawet wskazać, że została uruchomiona poprawna gra. Zapewnienie ekranu powitalnego daje systemowi tę zawartość. Następnie gra informuje użytkownika, że pierwsza faza aktywacji została ukończona, zastępując statyczny ekran powitalny własnym interfejsem użytkownika po rozpoczęciu uruchamiania kodu.

Druga faza aktywacji obejmuje tworzenie i inicjowanie struktur krytycznych dla gry. Jeśli aplikacja może szybko utworzyć swój początkowy interfejs użytkownika z danymi dostępnymi po pierwszej fazie aktywacji, druga faza jest trywialna i możesz natychmiast wyświetlić interfejs użytkownika. W przeciwnym razie zalecamy, aby aplikacja wyświetlała stronę ładowania podczas inicjowania.

To, jak wygląda strona ładowania, zależy od Ciebie i może być taka prosta, jak wyświetlanie paska postępu lub pierścienia postępu. Kluczowym punktem jest to, że aplikacja wskazuje, że wykonuje zadania przed rozpoczęciem reakcji. W przypadku gry chcesz wyświetlić ekran początkowy, ale interfejs użytkownika wymaga załadowania niektórych obrazów i dźwięków z dysku do pamięci. Te zadania zajmują kilka sekund, więc aplikacja informuje użytkownika, zastępując ekran powitalny stroną ładowania, która pokazuje prostą animację związaną z tematem gry.

Trzeci etap rozpoczyna się po tym, jak gra uzyska minimalny zestaw informacji potrzebnych do stworzenia interaktywnego interfejsu użytkownika, który zastępuje stronę ładowania. W tym momencie jedynymi informacjami dostępnymi dla gry online jest zawartość ładowana z dysku przez aplikację. Gra może dostarczać wystarczającą ilość zawartości, aby utworzyć interaktywny interfejs użytkownika; ale ponieważ jest to gra online, nie będzie działać, dopóki nie łączy się z Internetem i pobiera dodatkowe informacje. Dopóki nie będą dostępne wszystkie informacje, które muszą być funkcjonalne, użytkownik może wchodzić w interakcję z interfejsem użytkownika, ale funkcje, które wymagają dodatkowych danych z Internetu, powinny przekazać opinię, że zawartość jest nadal ładowana. Może upłynąć trochę czasu, aż aplikacja stanie się w pełni funkcjonalna, dlatego ważne jest, aby funkcje mogły być udostępniane tak szybko, jak to możliwe.

Teraz, gdy zidentyfikowaliśmy trzy etapy aktywacji w grze online, związajmy je z rzeczywistym kodem.

Faza 1

Przed uruchomieniem aplikacji musi poinformować system o tym, co chce wyświetlić jako ekran powitalny. Robi to, podając obraz i kolor tła do elementu SplashScreen w manifeście aplikacji, jak w przykładzie. System Windows wyświetla to po rozpoczęciu aktywacji przez aplikację.

<Package ...>
  ...
  <Applications>
    <Application ...>
      <VisualElements ...>
        ...
        <SplashScreen Image="Images\splashscreen.png" BackgroundColor="#000000" />
        ...
      </VisualElements>
    </Application>
  </Applications>
</Package>

Aby uzyskać więcej informacji, zobacz Dodaj ekran powitalny.

Konstruktor aplikacji służy tylko do inicjowania struktur danych, które mają kluczowe znaczenie dla aplikacji. Konstruktor jest wywoływany tylko przy pierwszym uruchomieniu aplikacji i niekoniecznie za każdym razem, gdy aplikacja jest aktywowana. Na przykład konstruktor nie jest wywoływany dla aplikacji, która została uruchomiona, umieszczona w tle, a następnie aktywowana za pośrednictwem kontraktu wyszukiwania.

Faza 2

Istnieje wiele powodów aktywowania aplikacji, z których każda może być obsługiwana inaczej. Można zastąpić OnActivated, OnCachedFileUpdaterActivated, OnFileActivated, OnFileOpenPickerActivated, OnFileSavePickerActivated, OnLaunched, OnSearchActivatedi OnShareTargetActivated metody obsługi każdej przyczyny aktywacji. Jedną z czynności, które aplikacja musi wykonać w tych metodach, jest utworzenie interfejsu użytkownika, przypisanie go do Window.Content, a następnie wywołanie Window.Activate. W tym momencie ekran powitalny jest zastępowany przez interfejs użytkownika utworzony przez aplikację. Ta wizualizacja może być ekranem ładowania lub rzeczywistym interfejsem użytkownika aplikacji, jeśli podczas aktywacji dostępna jest wystarczająca ilość informacji, aby ją utworzyć.

public partial class App : Application
{
    // A handler for regular activation.
    async protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        base.OnLaunched(args);

        // Asynchronously restore state based on generic launch.

        // Create the ExtendedSplash screen which serves as a loading page while the
        // reader downloads the section information.
        ExtendedSplash eSplash = new ExtendedSplash();

        // Set the content of the window to the extended splash screen.
        Window.Current.Content = eSplash;

        // Notify the Window that the process of activation is completed
        Window.Current.Activate();
    }

    // a different handler for activation via the search contract
    async protected override void OnSearchActivated(SearchActivatedEventArgs args)
    {
        base.OnSearchActivated(args);

        // Do an asynchronous restore based on Search activation

        // the rest of the code is the same as the OnLaunched method
    }
}

partial class ExtendedSplash : Page
{
    // This is the UIELement that's the game's home page.
    private GameHomePage homePage;

    public ExtendedSplash()
    {
        InitializeComponent();
        homePage = new GameHomePage();
    }

    // Shown for demonstration purposes only.
    // This is typically autogenerated by Visual Studio.
    private void InitializeComponent()
    {
    }
}
    Partial Public Class App
    Inherits Application

    ' A handler for regular activation.
    Protected Overrides Async Sub OnLaunched(ByVal args As LaunchActivatedEventArgs)
        MyBase.OnLaunched(args)

        ' Asynchronously restore state based on generic launch.

        ' Create the ExtendedSplash screen which serves as a loading page while the
        ' reader downloads the section information.
        Dim eSplash As New ExtendedSplash()

        ' Set the content of the window to the extended splash screen.
        Window.Current.Content = eSplash

        ' Notify the Window that the process of activation is completed
        Window.Current.Activate()
    End Sub

    ' a different handler for activation via the search contract
    Protected Overrides Async Sub OnSearchActivated(ByVal args As SearchActivatedEventArgs)
        MyBase.OnSearchActivated(args)

        ' Do an asynchronous restore based on Search activation

        ' the rest of the code is the same as the OnLaunched method
    End Sub
End Class

Partial Friend Class ExtendedSplash
    Inherits Page

    Public Sub New()
        InitializeComponent()

        ' Downloading the data necessary for
        ' initial UI on a background thread.
        Task.Run(Sub() DownloadData())
    End Sub

    Private Sub DownloadData()
        ' Download data to populate the initial UI.

        ' Create the first page.
        Dim firstPage As New MainPage()

        ' Add the data just downloaded to the first page

        ' Replace the loading page, which is currently
        ' set as the window's content, with the initial UI for the app
        Window.Current.Content = firstPage
    End Sub

    ' Shown for demonstration purposes only.
    ' This is typically autogenerated by Visual Studio.
    Private Sub InitializeComponent()
    End Sub
End Class

Aplikacje, które wyświetlają stronę ładowania w procedurze obsługi aktywacji, rozpoczynają pracę w celu utworzenia interfejsu użytkownika w tle. Po utworzeniu tego elementu wystąpi jego zdarzenie FrameworkElement.Loaded. W obsłudze zdarzeń zastąp zawartość okna, która jest obecnie ekranem ładowania, nową stroną główną.

Niezwykle ważne jest, aby aplikacja z przedłużonym okresem inicjowania wyświetlała stronę ładowania. Oprócz przekazywania opinii użytkownika na temat procesu aktywacji proces zostanie zakończony, jeśli Window.Activate nie zostanie wywołana w ciągu 15 sekund od rozpoczęcia procesu aktywacji.

partial class GameHomePage : Page
{
    public GameHomePage()
    {
        InitializeComponent();

        // add a handler to be called when the home page has been loaded
        this.Loaded += ReaderHomePageLoaded;

        // load the minimal amount of image and sound data from disk necessary to create the home page.
    }

    void ReaderHomePageLoaded(object sender, RoutedEventArgs e)
    {
        // set the content of the window to the home page now that it's ready to be displayed.
        Window.Current.Content = this;
    }

    // Shown for demonstration purposes only.
    // This is typically autogenerated by Visual Studio.
    private void InitializeComponent()
    {
    }
}
    Partial Friend Class GameHomePage
    Inherits Page

    Public Sub New()
        InitializeComponent()

        ' add a handler to be called when the home page has been loaded
        AddHandler Me.Loaded, AddressOf ReaderHomePageLoaded

        ' load the minimal amount of image and sound data from disk necessary to create the home page.
    End Sub

    Private Sub ReaderHomePageLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' set the content of the window to the home page now that it's ready to be displayed.
        Window.Current.Content = Me
    End Sub

    ' Shown for demonstration purposes only.
    ' This is typically autogenerated by Visual Studio.
    Private Sub InitializeComponent()
    End Sub
End Class

Aby zapoznać się z przykładem korzystania z rozszerzonych ekranów powitalnych, zobacz przykładowy ekran powitalny .

Faza 3

Tylko dlatego, że aplikacja wyświetla interfejs użytkownika nie oznacza, że jest całkowicie gotowa do użycia. W przypadku naszej gry interfejs użytkownika jest wyświetlany z symbolami zastępczymi dla funkcji, które wymagają danych z Internetu. W tym momencie gra pobiera dodatkowe dane potrzebne, aby aplikacja była w pełni funkcjonalna i stopniowo włącza funkcje w miarę pozyskiwania danych.

Czasami większość zawartości potrzebnej do aktywacji może być spakowana za pomocą aplikacji. Tak jest w przypadku prostej gry. Dzięki temu proces aktywacji jest dość prosty. Ale wiele programów (takich jak czytelnicy wiadomości i widzowie zdjęć) musi ściągać informacje z Internetu, aby stać się funkcjonalne. Te dane mogą być duże i zająć sporo czasu na pobranie. Sposób pobierania tych danych przez aplikację podczas procesu aktywacji może mieć ogromny wpływ na postrzeganą wydajność aplikacji.

Możesz wyświetlić stronę ładowania, lub co gorsza, ekran startowy, przez kilka minut, jeśli aplikacja próbowałaby pobrać cały zestaw danych potrzebnych do działania podczas pierwszej lub drugiej fazy aktywacji. Dzięki temu aplikacja wygląda tak, jakby zawieszała się lub powodowała jej zakończenie przez system. Zalecamy pobranie przez aplikację minimalnej ilości danych w celu wyświetlenia interakcyjnego interfejsu użytkownika z elementami zastępczymi w fazie 2, a następnie progresywnego ładowania danych, które zastępują elementy zastępcze w fazie 3. Aby uzyskać więcej informacji na temat obsługi danych, zobacz Optimize ListView and GridView.

Jak dokładnie aplikacja reaguje na każdą fazę uruchamiania, jest całkowicie do Ciebie, ale zapewnienie użytkownikowi jak największej ilości opinii (ekran powitalny, ekran ładowania, interfejs użytkownika podczas ładowania danych) sprawia, że użytkownik czuje się tak, jakby aplikacja i system jako całość były szybkie.

Zminimalizuj zarządzane zestawy w ścieżce uruchamiania

Kod wielokrotnego użytku często występuje w postaci modułów (DLL) zawartych w projekcie. Ładowanie tych modułów wymaga uzyskania dostępu do dysku, a jak można sobie wyobrazić, koszt tego może się zwiększyć. Ma to największy wpływ na zimny start, ale może mieć wpływ na ciepły start również. W przypadku języka C# i Visual Basic środowisko CLR próbuje opóźnić ten koszt tak długo, jak to możliwe, ładując zestawy na żądanie. Oznacza to, że CLR nie ładuje modułu, dopóki metoda nie zostanie wykonana i nie odwoła się do tego modułu. Dlatego należy odwołać się tylko do zestawów niezbędnych do uruchomienia aplikacji w kodzie uruchamiania, aby clR nie ładowała niepotrzebnych modułów. Jeśli w ścieżce uruchamiania masz nieużywane ścieżki kodu, które mają niepotrzebne odwołania, możesz przenieść te ścieżki kodu do innych metod, aby uniknąć niepotrzebnych obciążeń.

Innym sposobem zmniejszenia obciążenia modułu jest połączenie modułów aplikacji. Ładowanie jednego dużego zestawu zwykle zajmuje mniej czasu niż ładowanie dwóch małych. Nie zawsze jest to możliwe i należy łączyć moduły tylko wtedy, gdy nie ma to istotnej różnicy w zakresie produktywności deweloperów ani możliwości ponownego tworzenia kodu. Możesz użyć narzędzi, takich jak PerfView lub Windows Performance Analyzer (WPA), aby dowiedzieć się, jakie moduły są ładowane podczas uruchamiania.

Tworzenie inteligentnych żądań internetowych

Możesz znacznie poprawić czas ładowania aplikacji, pakując jego zawartość lokalnie, w tym XAML, obrazy i inne pliki ważne dla aplikacji. Operacje dysków są szybsze niż operacje sieciowe. Jeśli aplikacja wymaga określonego pliku podczas inicjowania, możesz skrócić ogólny czas uruchamiania, ładując go z dysku zamiast pobierać go z serwera zdalnego.

Efektywne zarządzanie stronami dziennika i pamięci podręcznej

Kontrolka Ramka udostępnia funkcje nawigacji. Oferuje nawigację do strony (metoda Navigate), dziennik nawigacji (właściwości BackStack/ForwardStack, metody GoForward/GoBack), buforowanie stron (Page.NavigationCacheMode) oraz wsparcie dla serializacji (metoda GetNavigationState).

Wydajność, na którą należy zwrócić uwagę w przypadku Frame, dotyczy przede wszystkim rejestrowania i buforowania stron.

Dziennikowanie ramowe. Po przejściu do strony z elementem Frame.Navigate() element PageStackEntry dla bieżącej strony zostanie dodany do kolekcji Frame.BackStack. PageStackEntry jest stosunkowo mały, ale nie ma wbudowanego limitu rozmiaru kolekcji BackStack. Potencjalnie użytkownik może przechodzić w pętli i rozwijać tę kolekcję w nieskończoność.

Element PageStackEntry zawiera również parametr przekazany do metody Frame.Navigate(). Zaleca się, aby ten parametr był pierwotnym typem serializowalnym (takim jak int lub ciąg), aby umożliwić działanie metody Frame.GetNavigationState(). Jednak ten parametr może potencjalnie odwoływać się do obiektu, który odpowiada za bardziej znaczące ilości zestawów roboczych lub innych zasobów, dzięki czemu każdy wpis w backstack jest znacznie droższy. Możesz na przykład użyć pliku StorageFile jako parametru, a w związku z tym platforma BackStack zachowuje nieograniczoną liczbę otwartych plików.

W związku z tym zaleca się zachowanie małych parametrów nawigacji i ograniczenie rozmiaru aplikacji BackStack. BackStack to standardowy wektor (IList w języku C#, Platform::Vector w języku C++/CX), dzięki czemu można go przycinać po prostu przez usunięcie wpisów.

buforowanie stron. Domyślnie po przejściu do strony za pomocą metody Frame.Navigate tworzone jest nowe wystąpienie strony. Podobnie, jeśli przejdziesz z powrotem do poprzedniej strony za pomocą Frame.GoBack, zostanie przydzielone nowe wystąpienie tej strony.

Ramka oferuje jednak opcjonalną pamięć podręczną stron, która może zapobiec tym instancjacjom. Aby uzyskać stronę umieszczoną w pamięci podręcznej, użyj właściwości Page.NavigationCacheMode. Ustawienie tego trybu na Wymagane spowoduje wymuszenie buforowania strony, ustawienie go na Włączone umożliwi buforowanie. Domyślnie rozmiar pamięci podręcznej to 10 stron, ale można go zastąpić właściwością Frame.CacheSize. Wszystkie wymagane strony będą buforowane, a jeśli jest ich mniej niż liczba określona przez CacheSize, można również buforować strony z włączoną opcją.

Buforowanie stron internetowych może poprawić wydajność poprzez unikanie instancji, a tym samym poprawiając wydajność nawigacji. Buforowanie stron może zaszkodzić wydajności w wyniku nadmiernego buforowania, wpływając w ten sposób na pamięć operacyjną.

W związku z tym zaleca się użycie buforowania stron zgodnie z potrzebami aplikacji. Załóżmy na przykład, że masz aplikację, która wyświetla listę elementów w ramce, a po naciśnięciu elementu przechodzi do ramki do strony szczegółów dla tego elementu. Strona listy powinna być prawdopodobnie ustawiona na pamięć podręczną. Jeśli strona szczegółów jest taka sama dla wszystkich elementów, prawdopodobnie powinna być również buforowana. Ale jeśli strona szczegółów jest bardziej heterogeniczna, może być lepiej pozostawić buforowanie wyłączone.