Détection d'à-coups dans l'UI

Android affiche l'UI en générant un frame à partir de votre application et en l'affichant à l'écran. Si votre application souffre d'un rendu de l'interface utilisateur lent, alors le système est obligé de sauter des frames. Dans ce cas, l'utilisateur perçoit un scintillement récurrent à l'écran, appelé à-coup.

Les à-coups sont généralement dûs à une décélération ou un blocage des appels asynchrones sur le thread UI (dans la plupart des applications, il s'agit du thread principal). Vous pouvez utiliser les traces système pour identifier l'origine du problème.

Si vous utilisez Jetpack Compose, le meilleur moyen d'examiner les performances de rendu dans la trace consiste à activer le traçage de la composition. Pour en savoir plus sur les problèmes de performances courants de Compose, consultez Performances de Jetpack Compose.

Pour les applications Compose, suivez les étapes de ce guide lorsque vous avez besoin d'une vue macro de votre application. Les traces système présentées ici vous aident à identifier les à-coups causés par des problèmes au niveau du système qui bloquent le thread principal, tels que des E/S disque importantes, une récupération de mémoire agressive ou des goulots d'étranglement du rendu GPU. Utilisez le guide Performances de Jetpack Compose si vous avez isolé le problème d'à-coups au niveau de votre couche d'UI. Ce guide vous aide à corriger les inefficacités spécifiques à Compose, comme les recompositions excessives, la lecture de l'état dans la mauvaise phase ou l'utilisation de paramètres instables.

Détecter les à-coups sur Android 12 ou version ultérieure

Pour les appareils équipés d'Android 12 (niveau d'API 31) ou version ultérieure, une trace capturée est affichée dans la ligne Frames saccadées sous le volet Display du Profileur de processeur.

Pour détecter les à-coups, procédez comme suit :

  1. Dans Android Studio, sélectionnez View > Tool Windows > Profiler (Vue > Fenêtres d'outil > Profileur) ou cliquez sur Profile (Profil)  dans la barre d'outils.

    Si vous y êtes invité par la boîte de dialogue Select Deployment Target (Sélectionner une cible de déploiement), choisissez l'appareil sur lequel déployer votre application à des fins de profilage. Si vous avez connecté un appareil via USB, mais qu'il ne figure pas dans la liste, assurez-vous d'avoir activé le débogage USB.

  2. Cliquez n'importe où dans la chronologie du CPU pour ouvrir le Profileur de processeur.

  3. Sélectionnez System Trace (Trace système) dans le menu de configuration du Profileur de processeur, puis cliquez sur Save (Enregistrer). Une fois que vous avez terminé d'interagir avec votre application, cliquez sur Arrêter.

  4. La piste Janky frames (Frames saccadés) doit s'afficher sous Display (Affichage). Par défaut, le profileur n'affiche que les frames irréguliers comme candidats à une enquête. Dans chaque frame saccadé, la partie rouge met en évidence la durée écoulée entre l'affichage du frame et son délai d'affichage. Capture d'écran de la piste des frames saccadés

  5. Lorsque vous trouvez un frame saccadé, cliquez dessus. Vous pouvez également appuyer sur M pour régler le zoom sur le frame sélectionné. Les événements pertinents sont mis en évidence dans ces threads : le thread principal, RenderThread et GPU completion. Capture d'écran du profileur montrant les frames saccadés et les threads principaux

  6. Vous pouvez aussi afficher tous les frames ou une répartition du délai d'affichage en cochant respectivement les cases All Frames (Tous les frames) et Lifecycle (Cycle de vie). Capture d'écran du profileur comme ci-dessus, mais avec les cases "All Frames" (Tous les frames) et "Lifecycle" (Cycle de vie) cochées

Détecter les à-coups sur Android 11

Pour les appareils équipés d'Android 11 (niveau d'API 30), une trace capturée est affichée dans la section Cycle de vie de la frame du Profileur de processeur.

Section Cycle de vie de la frame avec les différentes sections

La section Cycle de vie de la frame contient le nom de la couche et quatre lignes. Chaque ligne représente une étape du pipeline de rendu des frames. Les éléments du cycle de vie de la frame sont les suivants :

  1. Cycle de vie de la frame (nom de la couche) : le titre de la section contient le nom de la couche entre parenthèses. Une couche est une unité de composition unique.
  2. Application : cette ligne indique le moment où le tampon a été retiré de la file d'attente par l'application jusqu'au moment où il a été remis dans la file d'attente. Cela correspond généralement aux événements de trace dans RenderThread.
  3. Attente du GPU : cette ligne indique la durée pendant laquelle le tampon a appartenu au GPU. Il s'agit du temps entre le moment où le tampon est envoyé au GPU et le moment où le GPU a fini de travailler sur le tampon. Cela ne signifie pas que le GPU ne fonctionnait que sur ce tampon pendant cette période. Pour obtenir des informations détaillées sur le fonctionnement du GPU au cours d'une période donnée, vous pouvez utiliser Android GPU Inspector.
  4. Composition : cette ligne indique le temps écoulé entre le moment où SurfaceFlinger est appliqué au tampon et l'envoie pour composition, jusqu'à l'envoi du tampon à l'écran.
  5. Frames affichées à l'écran : cette ligne indique la durée d'affichage de la frame sur l'écran.

La section Cycle de vie de la frame illustre la façon dont un tampon d'image se déplace entre les différentes étapes du pipeline du rendu. Les frames sont codées par couleur afin de faciliter le suivi d'une frame en particulier.

Android Studio affiche également toutes les frames dans la trace sous forme de tableau dans l'onglet Toutes les frames.

Un tableau de toutes les frames de la trace dans l'onglet "Toutes les frames"

Les colonnes Frame #, Application, Wait for GPU (Attente du GPU) et Composition représentent les mêmes données que les lignes dans la section Cycle de vie du frame, comme indiqué ci-dessus. La colonne Durée de la frame représente le temps écoulé entre le lancement de l'application et l'affichage des frames sur l'écran. Il s'agit du temps nécessaire pour afficher d'un frame du début à la fin.

Vous pouvez trier le tableau des frames selon n'importe quelle colonne pour trouver rapidement la frame la plus courte ou la plus longue. Le tableau est également compatible avec les commandes de pagination qui vous aident à parcourir des centaines de frames.

Pour détecter et analyser les à-coups sur Android 11, procédez comme suit :

  1. Triez la table Toutes les frames par ordre décroissant sur la colonne Application afin que les frames les plus longues apparaissent en premier.

    Colonne Application triée par ordre décroissant

  2. Identifiez les frames les plus longues et sélectionnez la ligne du tableau. Cela effectue un zoom sur la frame sélectionnée dans la vue chronologique située à gauche.

    Vue chronologique à côté du tableau des frames

  3. Recherchez les threads pertinents dans les sections Cycle de vie de la frame et Threads.

    Sections Cycle de vie de la frame et Threads

Détecter les à-coups sur Android 10 ou version antérieure

Pour les appareils équipés d'Android 10 (niveau d'API 29) ou version antérieure, les informations pertinentes sur le pipeline des graphismes du système d'exploitation sont présentées dans une section de la trace système du Profileur de processeur appelée Display.

Fenêtre d'affichage de l'interface utilisateur

  • Frames : cette section présente le thread UI et les événements de trace RenderThread dans votre application. Les événements de plus de 16 ms sont colorés en rouge pour mettre en évidence les éventuels à-coups, car ils dépassent le délai d'affichage de 60 frames par seconde (FPS).
  • SurfaceFlinger : cette section indique à quel moment l'outil SurfaceFlinger traite les tampons de frame. SurfaceFlinger est un processus système chargé d'envoyer des tampons à afficher.
  • VSYNC : cette section affiche le VSYNC, un signal qui synchronise le pipeline d'affichage. Sur la ligne est affichée le signal VSYNC de l'application, qui apparaît lorsque votre application commence trop tard. En général, cela se produit parce que le thread UI est occupé. Un scintillement visible s'affiche à l'écran lors d'une animation et augmente la latence d'entrée jusqu'à la fin de l'animation ou du défilement. Cela est particulièrement important à prendre en compte pour les écrans à fréquence d'actualisation élevée, car ils peuvent se produire plus de 60 fois par seconde ou à un rythme variable.
  • BufferQueue : cette section indique le nombre de tampons de frame en file d'attente et en attente de leur utilisation par SurfaceFlinger. Pour les applications déployées sur des appareils équipés d'Android 9 (niveau d'API 28) ou version ultérieure, cette ligne indique le nombre de tampons de la surface BufferQueue de l'application (0, 1 ou 2). BufferQueue peut vous aider à comprendre l'état des tampons de frame lorsqu'ils transitent entre les composants graphiques d'Android. Par exemple, la valeur 2 signifie que l'application est actuellement mise en mémoire tampon trois fois, ce qui entraîne une latence d'entrée accrue.

La section Affichage fournit des signaux utiles pour détecter les à-coups potentiels (par exemple, lorsque le thread UI ou RenderThread prend plus de 16 ms). Pour en connaître les causes exactes, vous pouvez examiner la section Threads, qui indique les threads en rapport avec le rendu de l'interface utilisateur.

Section "Threads" sous "Affichage"

Dans la figure ci-dessus, la section Threads affiche le thread UI (java.com.google.samples.apps.iosched), RenderThread et le thread GPU completion. Il s'agit des threads en rapport avec l'affichage de l'interface utilisateur et qui peuvent contribuer aux à-coups.

Pour détecter les à-coups sous Android 10 ou version antérieure, procédez comme suit :

  1. Consultez la ligne Frames dans Display. Les frames en rouge sont de bons candidats pour une enquête.

    Section Frames sous Display

  2. Une fois que vous avez trouvé une frame sacadée, faites un zoom avant en appuyant sur W ou en faisant défiler la molette de la souris tout en maintenant la touche Ctrl enfoncée (Commande sur macOS). Continuez à zoomer jusqu'à ce que les événements de trace commencent à s'afficher dans le thread UI et RenderThread.

    Événements de trace dans le thread UI et RenderThread

    Dans la figure ci-dessus, Choreographer#doFrame montre à quel moment le thread UI appelle Choreographer pour coordonner l'animation, la mise en page, le dessin et les processus associés. DrawFrames montre lorsque RenderThread se forme et envoie des commandes de dessin réelles au GPU.

  3. Si vous constatez un événement de trace particulièrement long sur le thread principal, effectuez un zoom avant pour identifier le composant d'UI ou la fonction composable qui retarde le frame.

Enquête avancée avec Perfetto

La tâche de profilage de trace système Android Studio est optimisée par Perfetto. Si vous rencontrez des problèmes de rendu complexes et que vous avez besoin de requêtes SQL personnalisées ou d'une navigation avancée dans la timeline, vous pouvez analyser votre trace en dehors de l'IDE.

Exportez votre trace système depuis Android Studio en cliquant sur l'icône Exporter la trace dans le volet "Profileur", puis faites glisser le fichier obtenu dans l'interface utilisateur Perfetto basée sur le Web. Cela fournit un environnement dédié à l'analyse des performances au niveau du système. Pour savoir comment interpréter les détails du pipeline graphique de l'OS, tels que VSYNC, SurfaceFlinger et les pistes de la Frame Timeline, consultez la documentation officielle de Perfetto.

En savoir plus

Pour en savoir plus sur la façon de réduire les à-coups, consultez la section Principales sources d'à-coups.