Évaluation des performances

Utilisez Simpleperf pour évaluer les performances d'un appareil. Simpleperf est un outil de profilage natif pour les applications et les processus natifs sur Android. Utilisez CPU Profiler pour inspecter l'utilisation du processeur de l'application et l'activité des threads en temps réel.

Il existe deux indicateurs de performance visibles par l'utilisateur :

  • Performances prévisibles et perceptibles . L'interface utilisateur (UI) supprime-t-elle des images ou s'affiche-t-elle systématiquement à 60 FPS ? L'audio est-il lu sans artefacts ni éclats ? Quel est le délai entre le moment où l'utilisateur touche l'écran et l'effet affiché à l'écran ?
  • Durée requise pour les opérations plus longues (telles que l’ouverture d’applications).

Le premier est plus visible que le second. Les utilisateurs remarquent généralement des parasites, mais ils ne seront pas en mesure de déterminer le temps de démarrage d'une application entre 500 ms et 600 ms à moins qu'ils ne regardent deux appareils côte à côte. La latence tactile est immédiatement perceptible et contribue de manière significative à la perception d'un appareil.

Par conséquent, dans un appareil rapide, le pipeline d’interface utilisateur est l’élément le plus important du système, autre que ce qui est nécessaire pour maintenir le pipeline d’interface utilisateur fonctionnel. Cela signifie que le pipeline d’interface utilisateur doit préempter tout autre travail qui n’est pas nécessaire pour une interface utilisateur fluide. Pour maintenir une interface utilisateur fluide, la synchronisation en arrière-plan, la livraison des notifications et les travaux similaires doivent tous être retardés si le travail de l'interface utilisateur peut être exécuté. Il est acceptable d’échanger les performances d’opérations plus longues (runtime HDR+, démarrage d’application, etc.) pour conserver une interface utilisateur fluide.

Capacité vs gigue

Lorsque l'on considère les performances de l'appareil, la capacité et la gigue sont deux mesures significatives.

Capacité

La capacité est la quantité totale d'une ressource que l'appareil possède sur une certaine période de temps. Il peut s'agir de ressources CPU, de ressources GPU, de ressources d'E/S, de ressources réseau, de bande passante mémoire ou de toute autre mesure similaire. Lors de l'examen des performances de l'ensemble du système, il peut être utile d'abstraire les composants individuels et de supposer une seule métrique qui détermine les performances (en particulier lors du réglage d'un nouvel appareil, car les charges de travail exécutées sur cet appareil sont probablement fixes).

La capacité d'un système varie en fonction des ressources informatiques en ligne. Changer la fréquence du CPU/GPU est le principal moyen de modifier la capacité, mais il en existe d'autres, comme la modification du nombre de cœurs de CPU en ligne. En conséquence, la capacité d’un système correspond à la consommation d’énergie ; un changement de capacité entraîne toujours un changement similaire dans la consommation d’énergie.

La capacité requise à un moment donné est largement déterminée par l’application en cours d’exécution. En conséquence, la plateforme ne peut pas faire grand-chose pour ajuster la capacité requise pour une charge de travail donnée, et les moyens pour y parvenir se limitent à des améliorations du runtime (framework Android, ART, Bionic, compilateur/pilotes GPU, noyau).

Gigue

Même si la capacité requise pour une charge de travail est facile à déterminer, la gigue est un concept plus nébuleux. Pour une bonne introduction à la gigue en tant qu'obstacle aux systèmes rapides, reportez-vous au CAS DES PERFORMANCES MANQUANTES DU SUPERcalculateur : OBTENIR DES PERFORMANCES OPTIMALES SUR LES 8 192 PROCESSEURS D'ASCl Q . (Il s'agit d'une enquête sur les raisons pour lesquelles le supercalculateur ASCI Q n'a pas atteint les performances attendues et constitue une excellente introduction à l'optimisation des grands systèmes.)

Cette page utilise le terme gigue pour décrire ce que l'article ASCI Q appelle bruit . La gigue est le comportement aléatoire du système qui empêche l'exécution d'un travail perceptible. Il s'agit souvent d'un travail qui doit être exécuté, mais il peut ne pas être soumis à des exigences strictes en matière de calendrier qui l'obligent à être exécuté à un moment donné. Parce qu’elle est aléatoire, il est extrêmement difficile de réfuter l’existence de la gigue pour une charge de travail donnée. Il est également extrêmement difficile de prouver qu’une source connue de gigue est à l’origine d’un problème de performances particulier. Les outils les plus couramment utilisés pour diagnostiquer les causes de gigue (tels que le traçage ou la journalisation) peuvent introduire leur propre gigue.

Les sources de gigue rencontrées dans les implémentations réelles d'Android incluent :

  • Retard du planificateur
  • Gestionnaires d'interruptions
  • Le code du pilote s'exécute trop longtemps avec la préemption ou les interruptions désactivées
  • Softirqs de longue durée
  • Conflit de verrouillage (application, framework, pilote du noyau, verrouillage du classeur, verrouillage mmap)
  • Conflit de descripteur de fichier dans lequel un thread de faible priorité détient le verrou sur un fichier, empêchant ainsi un thread de haute priorité de s'exécuter
  • Exécution de code critique pour l'interface utilisateur dans les files d'attente de travail où il pourrait être retardé
  • Transitions d'inactivité du processeur
  • Enregistrement
  • Retards d'E/S
  • Création de processus inutiles (par exemple, diffusions CONNECTIVITY_CHANGE)
  • Trafic du cache de page causé par une mémoire libre insuffisante

La durée requise pour une période de gigue donnée peut ou non diminuer à mesure que la capacité augmente. Par exemple, si un pilote laisse les interruptions désactivées en attendant une lecture sur un bus i2c, cela prendra un temps fixe, que le processeur soit à 384 MHz ou à 2 GHz. L'augmentation de la capacité n'est pas une solution réalisable pour améliorer les performances lorsque la gigue est impliquée. Par conséquent, des processeurs plus rapides n’amélioreront généralement pas les performances dans des situations de gigue limitée.

Enfin, contrairement à la capacité, la gigue relève presque entièrement du fournisseur du système.

Consommation de mémoire

La consommation de mémoire est traditionnellement imputée aux mauvaises performances. Bien que la consommation en elle-même ne soit pas un problème de performances, elle peut provoquer une instabilité via une surcharge de lowmemorykiller, des redémarrages de services et une destruction du cache de pages. La réduction de la consommation de mémoire peut éviter les causes directes de mauvaises performances, mais il peut y avoir d'autres améliorations ciblées qui évitent également ces causes (par exemple, épingler le framework pour éviter qu'il ne soit paginé lorsqu'il le sera peu de temps après).

Analyse des performances initiales de l'appareil

Partir d'un système fonctionnel mais peu performant et tenter de corriger le comportement du système en examinant des cas individuels de mauvaises performances visibles par l'utilisateur n'est pas une bonne stratégie. Étant donné que les mauvaises performances ne sont généralement pas facilement reproductibles (c'est-à-dire la gigue) ou qu'elles constituent un problème d'application, un trop grand nombre de variables dans l'ensemble du système empêchent cette stratégie d'être efficace. Par conséquent, il est très facile de mal identifier les causes et d’apporter des améliorations mineures tout en passant à côté d’opportunités systémiques permettant d’améliorer les performances du système.

Utilisez plutôt l’approche générale suivante lorsque vous ouvrez un nouvel appareil :

  1. Obtenez le démarrage du système sur l'interface utilisateur avec tous les pilotes en cours d'exécution et certains paramètres de base du régulateur de fréquence (si vous modifiez les paramètres du régulateur de fréquence, répétez toutes les étapes ci-dessous).
  2. Assurez-vous que le noyau prend en charge le point de trace sched_blocked_reason ainsi que d'autres points de trace dans le pipeline d'affichage qui indiquent le moment où la trame est transmise à l'écran.
  3. Prenez de longues traces de l'ensemble du pipeline de l'interface utilisateur (depuis la réception des entrées via une IRQ jusqu'à l'analyse finale) tout en exécutant une charge de travail légère et cohérente (par exemple, UiBench ou le test de balle dans TouchLatency) .
  4. Corrigez les chutes de trame détectées dans la charge de travail légère et cohérente.
  5. Répétez les étapes 3 et 4 jusqu'à ce que vous puissiez exécuter sans perte d'images pendant plus de 20 secondes à la fois.
  6. Passez à d’autres sources de parasites visibles par l’utilisateur.

D'autres choses simples que vous pouvez faire dès le début de l'affichage de l'appareil incluent :

  • Assurez-vous que votre noyau dispose du correctif tracepoint sched_blocked_reason . Ce point de trace est activé avec la catégorie de trace sched dans systrace et fournit la fonction responsable de la mise en veille lorsque ce thread entre en veille ininterrompue. Il est essentiel pour l’analyse des performances, car le sommeil ininterrompu est un indicateur très courant de gigue.
  • Assurez-vous de disposer d'un traçage suffisant pour le GPU et les pipelines d'affichage. Sur les SOC Qualcomm récents, les points de trace sont activés à l'aide de :
  • adb shell "echo 1 > /d/tracing/events/kgsl/enable"
    adb shell "echo 1 > /d/tracing/events/mdss/enable"
    

    Ces événements restent activés lorsque vous exécutez systrace afin que vous puissiez voir des informations supplémentaires dans la trace sur le pipeline d'affichage (MDSS) dans la section mdss_fb0 . Sur les SOC Qualcomm, vous ne verrez aucune information supplémentaire sur le GPU dans la vue systrace standard, mais les résultats sont présents dans la trace elle-même (pour plus de détails, voir Comprendre systrace ).

    Ce que vous attendez de ce type de suivi d'affichage, c'est un événement unique qui indique directement qu'une image a été transmise à l'écran. À partir de là, vous pouvez déterminer si vous avez atteint votre temps d’image avec succès ; si l'événement X n se produit moins de 16,7 ms après l'événement X n-1 (en supposant un affichage à 60 Hz), alors vous savez que vous n'avez pas effectué de secousse. Si votre SOC ne fournit pas de tels signaux, travaillez avec votre fournisseur pour les obtenir. Le débogage de la gigue est extrêmement difficile sans un signal définitif de fin de trame.

Utiliser des benchmarks synthétiques

Les benchmarks synthétiques sont utiles pour garantir la présence des fonctionnalités de base d'un appareil. Cependant, traiter les benchmarks comme un indicateur des performances perçues de l’appareil n’est pas utile.

Sur la base des expériences avec les SOC, les différences de performances de référence synthétiques entre les SOC ne sont pas corrélées à une différence similaire dans les performances perceptibles de l'interface utilisateur (nombre d'images perdues, durée d'image au 99e percentile, etc.). Les références synthétiques sont des références de capacité uniquement ; la gigue a un impact sur les performances mesurées de ces benchmarks uniquement en volant du temps sur le fonctionnement global du benchmark. En conséquence, les scores de référence synthétiques ne sont pour la plupart pas pertinents en tant que mesure des performances perçues par les utilisateurs.

Considérez deux SOC exécutant Benchmark X qui restituent 1 000 images d'interface utilisateur et rapportent le temps de rendu total (un score inférieur est meilleur).

  • SOC 1 restitue chaque image de Benchmark X en 10 ms et obtient un score de 10 000.
  • SOC 2 restitue 99 % des images en 1 ms mais 1 % des images en 100 ms et obtient un score de 19 900, un score nettement meilleur.

Si le benchmark est indicatif des performances réelles de l’interface utilisateur, SOC 2 serait inutilisable. En supposant un taux de rafraîchissement de 60 Hz, le SOC 2 aurait une image saccadée toutes les 1,5 s de fonctionnement. Pendant ce temps, le SOC 1 (le SOC le plus lent selon Benchmark X) serait parfaitement fluide.

Utiliser les rapports de bogues

Les rapports de bugs sont parfois utiles pour l'analyse des performances, mais comme ils sont si lourds, ils sont rarement utiles pour déboguer les problèmes sporadiques de spam. Ils peuvent fournir des indications sur ce que faisait le système à un moment donné, en particulier si le problème concernait une transition d'application (qui est enregistrée dans un rapport de bogue). Les rapports de bogues peuvent également indiquer quand quelque chose ne va pas de manière plus générale avec le système, ce qui pourrait réduire sa capacité effective (comme une limitation thermique ou une fragmentation de la mémoire).

Utilisation de TouchLatency

Plusieurs exemples de mauvais comportement proviennent de TouchLatency, qui est la charge de travail périodique préférée utilisée pour le Pixel et le Pixel XL. Il est disponible sur frameworks/base/tests/TouchLatency et dispose de deux modes : latence tactile et balle rebondissante (pour changer de mode, cliquez sur le bouton dans le coin supérieur droit).

Le test de la balle rebondissante est aussi simple qu'il y paraît : une balle rebondit indéfiniment sur l'écran, quelle que soit la saisie de l'utilisateur. C'est généralement aussi de loin le test le plus difficile à exécuter parfaitement, mais plus il se rapproche d'une exécution sans perte d'images, meilleur sera votre appareil. Le test de la balle rebondissante est difficile car il s'agit d'une charge de travail triviale mais parfaitement cohérente qui s'exécute à une horloge très basse (cela suppose que l'appareil dispose d'un régulateur de fréquence ; si l'appareil fonctionne à la place avec des horloges fixes, downclockez le CPU/GPU à un niveau proche du minimum). lors de l'exécution du test de balle rebondissante pour la première fois). À mesure que le système se met au repos et que les horloges se rapprochent du mode veille, le temps CPU/GPU requis par image augmente. Vous pouvez regarder le ballon et voir les choses se passent mal, et vous pourrez également voir les images manquées dans Systrace.

La charge de travail étant si cohérente, vous pouvez identifier la plupart des sources de gigue beaucoup plus facilement que dans la plupart des charges de travail visibles par l'utilisateur en suivant exactement ce qui s'exécute sur le système pendant chaque image manquée au lieu du pipeline de l'interface utilisateur. Les horloges inférieures amplifient les effets de la gigue en augmentant la probabilité que toute gigue provoque une perte d'image. Par conséquent, plus TouchLatency est proche de 60 FPS, moins vous risquez d'avoir de mauvais comportements du système qui provoquent des parasites sporadiques et difficiles à reproduire dans les applications plus volumineuses.

Comme la gigue est souvent (mais pas toujours) invariante en fonction de la vitesse d'horloge, utilisez un test qui s'exécute à des horloges très basses pour diagnostiquer la gigue pour les raisons suivantes :

  • Toute gigue n’est pas invariante en fonction de la vitesse d’horloge ; de nombreuses sources consomment simplement du temps CPU.
  • Le gouverneur devrait rapprocher le temps de trame moyen de la date limite en ralentissant, de sorte que le temps passé à exécuter des travaux non liés à l'interface utilisateur puisse le pousser au-delà de la suppression d'un cadre.