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 :
- Des performances prévisibles et perceptibles . L'interface utilisateur (UI) perd-elle des images ou s'affiche-t-elle systématiquement à 60 images par seconde ? L'audio est-il lu sans artefacts ni sauts ? Quel est le délai entre le moment où l'utilisateur touche l'écran et l'effet affiché à l'écran ?
- Durée nécessaire pour des opérations plus longues (telles que l'ouverture d'applications).
Le premier est plus perceptible que le second. Les utilisateurs remarquent généralement le jank, mais ils ne pourront pas distinguer le temps de démarrage de l'application de 500 ms contre 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 la chose la plus importante 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 anticiper 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 (exécution HDR+, démarrage d'application, etc.) pour maintenir 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 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 nouveau périphérique, car les charges de travail exécutées sur ce périphérique sont probablement fixes).
La capacité d'un système varie en fonction des ressources informatiques en ligne. La modification de la fréquence 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 processeur 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 de 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 plate-forme ne peut pas faire grand-chose pour ajuster la capacité requise pour une charge de travail donnée, et les moyens pour le faire se limitent à des améliorations d'exécution (framework Android, ART, Bionic, compilateur/pilotes GPU, noyau).
Gigue
Alors que la capacité requise pour une charge de travail est facile à voir, la gigue est un concept plus nébuleux. Pour une bonne introduction à la gigue en tant qu'obstacle aux systèmes rapides, reportez-vous à LE 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 de grands systèmes.)
Cette page utilise le terme gigue pour décrire ce que l'article ASCI Q appelle le 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 se peut qu'il n'y ait pas d'exigences de temps strictes qui l'obligent à s'exécuter à un moment donné. Parce qu'il 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 était la cause 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, verrou de classeur, verrou mmap)
- Conflit de descripteur de fichier où un thread de faible priorité détient le verrou sur un fichier, empêchant un thread de haute priorité de s'exécuter
- Exécution de code critique pour l'interface utilisateur dans des files d'attente où il pourrait être retardé
- Transitions d'inactivité du processeur
- Enregistrement
- Délais d'E/S
- Création de processus inutiles (par exemple, diffusions CONNECTIVITY_CHANGE)
- Écrasement du cache de page causé par une mémoire libre insuffisante
La quantité de temps requise pour une période donnée de gigue peut ou non diminuer à mesure que la capacité augmente. Par exemple, si un pilote laisse les interruptions désactivées en attendant une lecture à travers 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, les processeurs plus rapides n'améliorent généralement pas les performances dans les situations de contraintes de gigue.
Enfin, contrairement à la capacité, la gigue relève presque entièrement du domaine du fournisseur du système.
Consommation mémoire
La consommation de mémoire est traditionnellement blâmée pour les mauvaises performances. Bien que la consommation elle-même ne soit pas un problème de performances, elle peut provoquer une gigue via une surcharge de lowmemorykiller, des redémarrages de service et un vidage du cache de page. 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 l'empêcher d'être paginé lorsqu'il sera paginé 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 performances médiocres visibles par l'utilisateur n'est pas une bonne stratégie. Étant donné que les performances médiocres ne sont généralement pas facilement reproductibles (c'est-à-dire la gigue) ou qu'il s'agit d'un problème d'application, trop de variables dans le système complet 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 ratant des opportunités systémiques pour corriger les performances dans l'ensemble du système.
Au lieu de cela, utilisez l'approche générale suivante lors de la création d'un nouvel appareil :
- Faites démarrer le 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).
- Assurez-vous que le noyau prend en charge le point de
sched_blocked_reason
ainsi que d'autres points de trace dans le pipeline d'affichage qui indiquent quand l'image est livrée à l'affichage. - Prenez de longues traces de l'ensemble du pipeline de l'interface utilisateur (de la réception des entrées via un IRQ à 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) .
- Corrigez les chutes de trame détectées dans la charge de travail légère et cohérente.
- Répétez les étapes 3 et 4 jusqu'à ce que vous puissiez exécuter avec zéro image perdue pendant plus de 20 secondes à la fois.
- Passez à d'autres sources de jank visibles par l'utilisateur.
D'autres choses simples que vous pouvez faire dès le début de la mise en place de l'appareil incluent :
- Assurez-vous que votre noyau dispose du correctif de point de trace 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 sans interruption. Il est essentiel pour l'analyse des performances car la veille ininterrompue est un indicateur très courant de gigue.
- Assurez-vous que vous disposez d'un suivi 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 traçage d'affichage est un événement unique qui indique directement qu'une image a été livrée à l'affichage. À partir de là, vous pouvez déterminer si vous avez atteint votre temps de trame 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 jank. 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 d'achèvement de trame.
Utiliser des benchmarks synthétiques
Les benchmarks synthétiques sont utiles pour s'assurer que les fonctionnalités de base d'un appareil sont présentes. 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 avec une différence similaire dans les performances perceptibles de l'interface utilisateur (nombre d'images perdues, temps d'image au 99e centile, etc.). Les benchmarks synthétiques sont des benchmarks de capacité uniquement ; la gigue n'affecte les performances mesurées de ces benchmarks qu'en volant du temps à l'opération en bloc du benchmark. Par conséquent, les scores de référence synthétiques ne sont généralement pas pertinents en tant que mesure des performances perçues par l'utilisateur.
Considérez deux SOC exécutant Benchmark X qui restituent 1 000 images d'interface utilisateur et signalent le temps de rendu total (un score inférieur est préférable).
- SOC 1 rend 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 la référence est indicative 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 seconde de fonctionnement. Pendant ce temps, le SOC 1 (le SOC le plus lent selon Benchmark X) serait parfaitement fluide.
Utilisation des rapports de bogues
Les rapports de bogues sont parfois utiles pour l'analyse des performances, mais parce qu'ils sont si lourds, ils sont rarement utiles pour déboguer des problèmes sporadiques. Ils peuvent fournir des indications sur ce que le système faisait à un moment donné, en particulier si le problème concernait une transition d'application (qui est consignée dans un rapport de bogue). Les rapports de bogue peuvent également indiquer quand quelque chose ne va pas avec le système, ce qui pourrait réduire sa capacité effective (comme la limitation thermique ou la 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 sur l'écran pour toujours, quelle que soit l'entrée de l'utilisateur. C'est généralement aussi de loin le test le plus difficile à exécuter parfaitement, mais plus il s'approche d'une exécution sans perte d'image, 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 au minimum lors de l'exécution du test de balle rebondissante pour la première fois). Au fur et à mesure que le système se met au repos et que les horloges se rapprochent de l'inactivité, le temps CPU/GPU requis par image augmente. Vous pouvez regarder la balle et voir les choses jank, et vous pourrez également voir les images manquées dans systrace.
Étant donné que la charge de travail est 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 trame manquée au lieu du pipeline de l'interface utilisateur. Les horloges inférieures amplifient les effets de la gigue en rendant plus probable que toute gigue provoque une perte de trame. Par conséquent, plus TouchLatency est proche de 60FPS, moins vous êtes susceptible d'avoir de mauvais comportements système qui provoquent des jank sporadiques et difficiles à reproduire dans des applications plus importantes.
Comme la gigue est souvent (mais pas toujours) invariante à la vitesse d'horloge, utilisez un test qui s'exécute à des horloges très basses pour diagnostiquer la gigue pour les raisons suivantes :
- Toutes les gigues ne sont pas invariantes à la vitesse d'horloge ; de nombreuses sources ne consomment que du temps CPU.
- Le gouverneur doit obtenir le temps de trame moyen proche de la date limite en décroissant, de sorte que le temps passé à exécuter des travaux non liés à l'interface utilisateur peut le pousser à la limite pour laisser tomber une trame.