Partager via


Meilleures pratiques pour les performances de démarrage de votre application

Créez des applications de plateforme Windows universelle (UWP) avec des temps de démarrage optimaux en améliorant la façon dont vous gérez le lancement et l’activation.

Meilleures pratiques pour les performances de démarrage de votre application

En partie, les utilisateurs perçoivent si votre application est rapide ou lente en fonction du temps nécessaire pour démarrer. Dans le cadre de cette rubrique, l’heure de démarrage d’une application commence lorsque l’utilisateur démarre l’application et se termine lorsque l’utilisateur peut interagir avec l’application de manière significative. Cette section fournit des suggestions sur la façon d’améliorer les performances de votre application au démarrage.

Mesure du temps de démarrage de votre application

Veillez à démarrer votre application quelques fois avant de mesurer son temps de démarrage. Cela vous donne une base de référence pour votre mesure et garantit que vous mesurez la durée de démarrage aussi courte que possible.

Au moment où votre application UWP arrive sur les ordinateurs de vos clients, votre application a été compilée avec la chaîne d’outils .NET Native. .NET Native est une technologie de compilation anticipée qui convertit MSIL en code machine exécutable en mode natif. Les applications .NET Native démarrent plus rapidement, utilisent moins de mémoire et utilisent moins de batterie que leurs équivalents MSIL. Les applications créées avec .NET Native sont liées statiquement dans un runtime personnalisé et la nouvelle version convergée de .NET Core qui peut s’exécuter sur tous les appareils, de sorte qu’elles ne dépendent pas de l’implémentation .NET intégrée. Sur votre ordinateur de développement, par défaut, votre application utilise .NET Native si vous la générez en mode « Mise en production » et utilise CoreCLR si vous la générez en mode « Débogage ». Vous pouvez le configurer dans Visual Studio à partir de la page Build dans « Propriétés » (C#) ou Compiler-Avancé> dans « Mon projet » (VB). Recherchez une case à cocher indiquant « Compiler avec la chaîne d’outils native .NET ».

Bien sûr, vous devez prendre des mesures qui sont représentatives de ce que l’utilisateur final connaîtra. Par conséquent, si vous ne savez pas que vous compilez votre application en code natif sur votre ordinateur de développement, vous pouvez exécuter l’outil Native Image Generator (Ngen.exe) pour précompiler votre application avant de mesurer son temps de démarrage.

La procédure suivante explique comment exécuter Ngen.exe pour précompiler votre application.

Pour exécuter Ngen.exe

  1. Exécutez votre application au moins une fois pour vous assurer que Ngen.exe la détecte.

  2. Ouvrez le planificateur de tâches en effectuant l’une des opérations suivantes :

    • Recherchez « Planificateur de tâches » à partir de l’écran de démarrage.
    • Exécutez « taskschd.msc ».
  3. Dans le volet gauche du planificateur de tâches , développez la Bibliothèque du Planificateur de Tâches .

  4. Étendez Microsoft.

  5. Étendez Windows.

  6. Sélectionnez .NET Framework.

  7. Sélectionnez .NET Framework NGEN 4.x dans la liste des tâches.

    Si vous utilisez un ordinateur 64 bits, il existe également un .NET Framework NGEN v4.x 64. Si vous créez une application 64 bits, sélectionnez . NET Framework NGEN v4.x 64.

  8. Dans le menu Action de , cliquez sur Exécuter.

Ngen.exe précompile toutes les applications sur l’ordinateur qui ont été utilisées et n’ont pas d’images natives. S’il existe beaucoup d’applications qui doivent être précompilées, cela peut prendre beaucoup de temps, mais les exécutions suivantes sont beaucoup plus rapides.

Lorsque vous recompilez votre application, l’image native n’est plus utilisée. Au lieu de cela, l’application est compilée juste-à-temps, ce qui signifie qu’elle est compilée au fur et à mesure que l’application s’exécute. Vous devez réexécuter Ngen.exe pour obtenir une nouvelle image native.

Différer le travail aussi longtemps que possible

Pour améliorer le temps de démarrage de votre application, effectuez uniquement le travail qui doit absolument être effectué pour permettre à l’utilisateur de commencer à interagir avec l’application. Cela peut être particulièrement utile si vous pouvez retarder le chargement d’assemblys supplémentaires. Le Common Language Runtime charge un assembly la première fois qu’il est utilisé. Si vous pouvez réduire le nombre d’assemblys chargés, vous pouvez améliorer le temps de démarrage de votre application et sa consommation de mémoire.

Effectuer un travail de longue durée indépendamment

Votre application peut être interactive même s’il existe des parties de l’application qui ne sont pas entièrement fonctionnelles. Par exemple, si votre application affiche des données qui prennent un certain temps à récupérer, vous pouvez faire en sorte que ce code s’exécute indépendamment du code de démarrage de l’application en récupérant les données de manière asynchrone. Lorsque les données sont disponibles, renseignez l’interface utilisateur de l’application avec les données.

La plupart des API de plateforme Windows universelle (UWP) qui récupèrent des données sont asynchrones. Vous allez donc probablement récupérer des données de façon asynchrone. Pour plus d’informations sur les API asynchrones, consultez Appeler des API asynchrones en C# ou Visual Basic. Si vous effectuez un travail qui n’utilise pas d’API asynchrones, vous pouvez utiliser la classe Task pour effectuer un travail de longue durée afin de ne pas empêcher l’utilisateur d’interagir avec l’application. Cela permet à votre application de répondre aux besoins de l’utilisateur pendant le chargement des données.

Si votre application prend un temps particulièrement long pour charger une partie de son interface utilisateur, envisagez d’ajouter une chaîne dans cette zone qui indique quelque chose comme « Obtention des données les plus récentes », afin que vos utilisateurs sachent que l’application est toujours en cours de traitement.

Réduire le temps de démarrage

Toutes les applications les plus simples nécessitent un temps de chargement de ressources, d’analyse XAML, de configuration de structures de données et d’exécution de logique lors de l’activation. Ici, nous analysons le processus d’activation en le cassant en trois phases. Nous fournissons également des conseils pour réduire le temps passé dans chaque phase et des techniques pour rendre chaque phase du démarrage de votre application plus agréable à l’utilisateur.

La période d’activation est le temps entre le moment où un utilisateur démarre l’application et le moment où l’application est fonctionnelle. Il s’agit d’un moment critique, car il s’agit de la première impression d’un utilisateur de votre application. Ils attendent des commentaires instantanés et continus du système et des applications. Le système et l’application sont perçus comme rompus ou mal conçus lorsque les applications ne démarrent pas rapidement. Pire encore, si une application prend trop de temps pour l’activer, le Gestionnaire de durée de vie des processus (PLM) peut le tuer, ou l’utilisateur peut le désinstaller.

Présentation des phases de démarrage

Le démarrage implique un certain nombre de pièces mobiles, et tous doivent être correctement coordonnés pour la meilleure expérience utilisateur. Les étapes suivantes se produisent entre le moment où votre utilisateur clique sur la vignette de votre application et celui où le contenu de l'application s'affiche.

  • L’interpréteur de commandes Windows démarre le processus et Main est appelé.
  • L’objet Application est créé.
    • (Modèle de projet) Le constructeur appelle InitializeComponent, ce qui fait qu'App.xaml est analysé et que des objets sont créés.
  • L’événement Application.OnLaunched est déclenché.
    • (ProjectTemplate) Le code de l’application crée un frame et accède à MainPage.
    • (ProjectTemplate) Le constructeur MainPage appelle InitializeComponent, ce qui permet à MainPage.xaml d’être analysé et des objets créés.
    • ProjectTemplate) Window.Current.Activate() est appelé.
  • La plateforme XAML exécute la passe de disposition, y compris Measure &Arrange.
    • La méthode ApplyTemplate entraîne la création du contenu du gabarit de contrôle pour chaque contrôle, ce qui représente généralement la majeure partie du temps de mise en page lors du démarrage.
  • On appelle la fonction de rendu pour créer des visuels pour l'ensemble du contenu de la fenêtre.
  • Le frame est présenté au Gestionnaire windows de bureau (DWM).

Réduisez vos efforts dans votre parcours entrepreneurial

Laissez votre chemin de code de démarrage libre de tout ce qui n’est pas nécessaire pour votre première image.

  • Si vous avez des DLL utilisateur contenant des contrôles qui ne sont pas nécessaires pendant la première image, envisagez de retarder leur chargement.
  • Si vous avez une partie de votre interface utilisateur dépendante des données du cloud, fractionnez cette interface utilisateur. Tout d’abord, affichez l’interface utilisateur qui n’est pas dépendante des données cloud et affichez de manière asynchrone l’interface utilisateur dépendante du cloud. Vous devez également envisager de mettre en cache les données localement afin que l’application fonctionne hors connexion ou ne soit pas affectée par la connectivité réseau lente.
  • Affichez l’interface utilisateur de progression si votre interface utilisateur attend des données.
  • Soyez prudent quant aux conceptions d’applications qui impliquent un grand nombre d’analyse de fichiers de configuration ou d’interface utilisateur générées dynamiquement par le code.

Réduire le nombre d’éléments

Les performances de démarrage dans une application XAML sont directement corrélées au nombre d’éléments que vous créez au démarrage. Moins d’éléments que vous créez, moins votre application prendra de temps pour démarrer. En guise d’évaluation approximative, prévoyez qu'il faut 1 ms pour créer chaque élément.

  • Les modèles utilisés dans les contrôles d’éléments peuvent avoir le plus d’impact, car ils sont répétés plusieurs fois. Consultez l'optimisation de l'interface utilisateur de ListView et GridView.
  • Les modèles UserControls et de contrôle seront développés. Ceux-ci doivent donc également être pris en compte.
  • Si vous créez un code XAML qui n’apparaît pas sur l’écran, vous devez justifier si ces éléments de XAML doivent être créés au démarrage.

La fenêtre Visual Studio Live Visual Tree affiche le nombre d’éléments enfants pour chaque nœud de l’arborescence.

Arborescence visuelle dynamique.

Utiliser le report. La réduction d’un élément ou la définition de son opacité sur 0 n’empêche pas la création de l’élément. À l’aide de x :Load ou x :DeferLoadStrategy, vous pouvez retarder le chargement d’un élément d’interface utilisateur et le charger si nécessaire. Cela permet de retarder le traitement de l’interface utilisateur qui n’est pas visible pendant l’écran de démarrage, afin que vous puissiez le charger si nécessaire, ou dans le cadre d’un ensemble de logiques retardées. Pour déclencher le chargement, vous devez uniquement appeler FindName pour l’élément. Pour un exemple et plus d'informations, consultez l'attribut x:Load et l'attribut x:DeferLoadStrategy .

virtualisation. Si vous avez du contenu de liste ou de répéteur dans votre interface utilisateur, il est vivement recommandé d’utiliser la virtualisation de l’interface utilisateur. Si l’interface utilisateur de liste n’est pas virtualisée, vous payez le coût de la création de tous les éléments au début et cela peut ralentir votre démarrage. Consultez l'optimisation de l'interface utilisateur de ListView et GridView.

Les performances des applications ne concernent pas seulement les performances brutes, mais aussi la perception. Changer l'ordre des opérations pour que les aspects visuels se produisent en premier donne généralement l'impression à l'utilisateur que l'application est plus rapide. Les utilisateurs considèrent l'application chargée lorsque le contenu est à l'écran. En règle générale, les applications doivent effectuer plusieurs opérations dans le cadre du démarrage, et pas toutes celles qui sont requises pour afficher l’interface utilisateur, de sorte que celles-ci doivent être retardées ou hiérarchisées plus bas que l’interface utilisateur.

Cette rubrique traite de la « première image » qui provient de l’animation/tv, et est une mesure de la durée pendant laquelle le contenu n’est pas vu par l’utilisateur final.

Améliorer la perception du démarrage

Utilisons l’exemple d’un jeu en ligne simple pour identifier chaque phase de démarrage et différentes techniques pour donner à l’utilisateur des commentaires tout au long du processus. Pour cet exemple, la première phase d’activation est le temps entre l’utilisateur appuyant sur la vignette du jeu et le jeu commençant à exécuter son code. Pendant ce temps, le système n’a pas de contenu à afficher à l’utilisateur pour même indiquer que le jeu approprié a démarré. Cependant, le fait de fournir un écran de démarrage met ce contenu à disposition du système. Le jeu informe ensuite l’utilisateur que la première phase d’activation est terminée en remplaçant l’écran de démarrage statique par son propre interface utilisateur lorsqu’il commence à exécuter du code.

La deuxième phase d’activation englobe la création et l’initialisation de structures critiques pour le jeu. Si une application peut rapidement créer son interface utilisateur initiale avec les données disponibles après la première phase d’activation, la deuxième phase est triviale et vous pouvez afficher immédiatement l’interface utilisateur. Sinon, nous vous recommandons d’afficher une page de chargement pendant son initialisation.

À quoi ressemble la page de chargement dépend de vous, et cela peut être aussi simple que l’affichage d’une barre de progression ou d’un cercle de progression. Le point clé est que l’application indique qu’elle effectue des tâches avant de devenir réactive. Dans le cas du jeu, il souhaite afficher son écran initial, mais cette interface utilisateur nécessite que certaines images et sons soient chargés du disque en mémoire. Ces tâches prennent quelques secondes, de sorte que l’application conserve l’utilisateur informé en remplaçant l’écran de démarrage par une page de chargement, qui montre une animation simple liée au thème du jeu.

La troisième étape commence une fois que le jeu a un ensemble minimal d’informations pour créer une interface utilisateur interactive, qui remplace la page de chargement. À ce stade, les seules informations disponibles pour le jeu en ligne sont le contenu que l’application a chargé à partir du disque. Le jeu peut être fourni avec suffisamment de contenu pour créer une interface utilisateur interactive ; mais parce qu’il s’agit d’un jeu en ligne, il ne sera pas fonctionnel tant qu’il se connecte à Internet et télécharge des informations supplémentaires. Tant qu’il n’a pas toutes les informations dont il a besoin pour être fonctionnel, l’utilisateur peut interagir avec l’interface, mais les fonctionnalités qui ont besoin de données supplémentaires depuis le web doivent indiquer que le contenu est toujours en cours de chargement. Il peut prendre un certain temps pour qu’une application devienne entièrement fonctionnelle. Il est donc important que la fonctionnalité soit rendue disponible dès que possible.

Maintenant que nous avons identifié les trois étapes d’activation dans le jeu en ligne, nous allons les lier au code réel.

Étape 1

Avant de démarrer une application, elle doit indiquer au système ce qu’elle souhaite afficher en tant qu’écran de démarrage. Il le fait en fournissant une image et une couleur d’arrière-plan à l’élément SplashScreen dans le manifeste d’une application, comme dans l’exemple. Windows affiche ceci une fois que l’activation de l’application a commencé.

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

Pour plus d'informations, voir Ajouter un écran d'accueil.

Utilisez le constructeur de l’application uniquement pour initialiser des structures de données critiques pour l’application. Le constructeur est appelé uniquement la première fois que l’application est exécutée et pas nécessairement chaque fois que l’application est activée. Par exemple, le constructeur n’est pas appelé pour une application qui a été exécutée, placée en arrière-plan, puis activée via le contrat de recherche.

Étape 2

Il existe plusieurs raisons pour lesquelles une application doit être activée, chacune d’elles pouvant être gérée différemment. Vous pouvez remplacer OnActivated , OnCachedFileUpdaterActivated, OnFileActivated, OnFileOpenPickerActivated, OnFileSavePickerActivated, OnLaunched , OnSearchActivatedet méthodes OnShareTargetActivated pour gérer chaque raison d’activation. L’une des opérations qu’une application doit effectuer dans ces méthodes est de créer une interface utilisateur, de l’affecter à Window.Content, puis d’appeler Window.Activate. À ce stade, l’écran de démarrage est remplacé par l’interface utilisateur créée par l’application. Ce visuel peut être soit un écran de chargement, soit l’interface utilisateur réelle de l’application si suffisamment d’informations sont disponibles lors de l’activation pour le créer.

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

Les applications qui affichent une page de chargement dans le gestionnaire d’activation commencent à créer l’interface utilisateur en arrière-plan. Une fois cet élément créé, son événement FrameworkElement.Loaded se produit. Dans le gestionnaire d’événements, vous remplacez le contenu de la fenêtre, qui est actuellement l’écran de chargement, par la page d’accueil nouvellement créée.

Il est essentiel qu’une application avec une période d’initialisation prolongée affiche une page de chargement. En plus de fournir des commentaires utilisateur sur le processus d’activation, le processus est arrêté si Window.Activate n’est pas appelé dans les 15 secondes suivant le début du processus d’activation.

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

Pour obtenir un exemple d’utilisation d’écrans de démarrage étendus, consultez l’exemple d’écran de démarrage.

Phase 3

Simplement parce que l’application a affiché l’interface utilisateur ne signifie pas qu’elle est entièrement prête à être utilisée. Dans le cas de notre jeu, l’interface utilisateur s’affiche avec des espaces réservés pour les fonctionnalités qui nécessitent des données à partir d’Internet. À ce stade, le jeu télécharge les données supplémentaires nécessaires pour rendre l’application entièrement fonctionnelle et active progressivement les fonctionnalités à mesure que les données sont acquises.

Parfois, une grande partie du contenu nécessaire à l’activation peut être empaquetée avec l’application. C’est le cas avec un jeu simple. Cela rend le processus d’activation assez simple. Mais de nombreux programmes (tels que les lecteurs d’actualités et les visionneuses de photos) doivent tirer des informations du web pour devenir fonctionnels. Ces données peuvent être volumineuses et prendre un certain temps de téléchargement. La façon dont l’application obtient ces données pendant le processus d’activation peut avoir un impact considérable sur les performances perçues d’une application.

Vous pouvez afficher une page de chargement, ou pire, un écran de démarrage, pendant quelques minutes si une application a essayé de télécharger un jeu de données entier dont elle a besoin pour les fonctionnalités de la phase 1 ou deux de l’activation. Cela peut donner l'impression qu'une application est bloquée ou entraîner sa fermeture par le système. Nous recommandons à une application de télécharger la quantité minimale de données pour afficher une interface utilisateur interactive avec des éléments d’espace réservé dans la phase 2, puis de charger progressivement des données, qui remplacent les éléments d’espace réservé, dans la phase 3. Pour plus d’informations sur la gestion des données, consultez Optimiser ListView et GridView.

La façon dont une application réagit exactement à chaque phase de démarrage est entièrement à vous, mais fournir à l’utilisateur autant de commentaires que possible (écran de démarrage, écran de chargement, interface utilisateur pendant les chargements de données) rend l’utilisateur comme si une application, et le système dans son ensemble, sont rapides.

Réduire les assemblies gérées dans le chemin de démarrage

Le code réutilisable se présente souvent sous la forme de modules (DLL) inclus dans un projet. Le chargement de ces modules nécessite l’accès au disque, et comme vous pouvez l’imaginer, le coût de cette opération peut s’ajouter. Cela a le plus grand impact sur le démarrage à froid, mais il peut également avoir un impact sur le démarrage chaud. Dans le cas de C# et Visual Basic, le CLR tente de retarder ce coût autant que possible en chargeant des assemblys à la demande. Autrement dit, le CLR ne charge pas un module tant qu’une méthode exécutée ne l’a pas référencée. Par conséquent, référencez uniquement les assemblys nécessaires au lancement de votre application dans le code de démarrage afin que le CLR ne charge pas les modules inutiles. Si vous avez des chemins de code inutilisés dans votre chemin d’accès de démarrage qui ont des références inutiles, vous pouvez déplacer ces chemins de code vers d’autres méthodes pour éviter les charges inutiles.

Une autre façon de réduire les chargements de modules consiste à combiner vos modules d’application. Le chargement d’un assembly volumineux prend généralement moins de temps que le chargement de deux petits. Cela n’est pas toujours possible et vous devez combiner des modules uniquement s’il ne fait aucune différence matérielle à la productivité des développeurs ou à la réutilisation du code. Vous pouvez utiliser des outils tels que PerfView ou WPA (Windows Performance Analyzer) pour savoir quels modules sont chargés au démarrage.

Effectuer des requêtes web intelligentes

Vous pouvez améliorer considérablement le temps de chargement d’une application en empaquetant son contenu localement, y compris XAML, images et tous les autres fichiers importants pour l’application. Les opérations de disque sont plus rapides que les opérations réseau. Si une application a besoin d’un fichier particulier lors de l’initialisation, vous pouvez réduire le temps de démarrage global en le chargeant à partir du disque au lieu de le récupérer à partir d’un serveur distant.

Journal et cache les pages efficacement

Le contrôleur Frame fournit des fonctionnalités de navigation. Il offre une navigation vers une page (méthode Navigate), la journalisation de navigation (propriétés BackStack/ForwardStack, la méthode GoForward/GoBack), la mise en cache de page (Page.NavigationCacheMode) et la prise en charge de la sérialisation (méthode GetNavigationState).

Les performances à prendre en compte avec Frame concernent principalement la journalisation et la mise en cache des pages.

journalisation de frame. Lorsque vous accédez à une page avec Frame.Navigate(), une PageStackEntry pour la page active est ajoutée à la collection Frame.BackStack. PageStackEntry est relativement petit, mais il n’existe aucune limite intégrée à la taille de la collection BackStack. Potentiellement, un utilisateur peut naviguer dans une boucle et développer indéfiniment cette collection.

PageStackEntry inclut également le paramètre passé à la méthode Frame.Navigate(). Il est recommandé que ce paramètre soit un type sérialisable primitif (tel qu’une int ou une chaîne), afin d’autoriser la méthode Frame.GetNavigationState() à fonctionner. Mais ce paramètre peut potentiellement référencer un objet qui représente des quantités plus importantes d’ensemble de travail ou d’autres ressources, ce qui rend chaque entrée dans BackStack beaucoup plus coûteuse. Par exemple, vous pouvez potentiellement utiliser un StorageFile en tant que paramètre, et par conséquent, backStack conserve un nombre indéfini de fichiers ouverts.

Par conséquent, il est recommandé de conserver les paramètres de navigation petits et de limiter la taille du BackStack. BackStack est un vecteur standard (IList en C#, Platform ::Vector en C++/CX), et peut donc être supprimé simplement en supprimant les entrées.

Mise en cache de page. Par défaut, lorsque vous accédez à une page avec la méthode Frame.Navigate, une nouvelle instance de la page est instanciée. De même, si vous revenez à la page précédente avec Frame.GoBack, une nouvelle instance de la page précédente est allouée.

Le frame offre toutefois un cache de page facultatif qui peut éviter ces instanciations. Pour obtenir une page placée dans le cache, utilisez la propriété Page.NavigationCacheMode. En réglant ce mode sur Obligatoire, la page sera forcément mise en cache, alors qu'en le réglant sur Activé, elle pourra être mise en cache. Par défaut, la taille du cache est de 10 pages, mais elle peut être remplacée par la propriété Frame.CacheSize. Toutes les pages requises sont mises en cache et, s’il y a moins de pages CacheSize Obligatoires, les pages activées peuvent également être mises en cache.

La mise en cache des pages peut aider les performances en évitant les instanciations et en améliorant ainsi les performances de navigation. La mise en cache des pages peut nuire aux performances en raison d'une mise en cache excessive, ce qui affecte l'ensemble de travail.

Par conséquent, il est recommandé d’utiliser la mise en cache des pages selon les besoins de votre application. Par exemple, supposons que vous disposez d’une application qui affiche une liste d’éléments dans un frame, et lorsque vous appuyez sur un élément, elle navigue vers une page de détails pour cet élément. La page de liste doit probablement être mise en cache. Si la page de détails est identique pour tous les éléments, elle doit probablement être mise en cache également. Mais si la page de détails est plus hétérogène, il peut être préférable de laisser la mise en cache désactivée.