Android 8.0 inclut des tests de performance des liaisons et des hwbinders pour le débit et la latence. De nombreux scénarios permettent de détecter les performances perceptibles exécuter de tels scénarios peut prendre beaucoup de temps et les résultats sont souvent est indisponible avant l'intégration d'un système. Utiliser les performances fournies facilitent les tests pendant le développement, la détection de problèmes graves plus tôt et améliorer l'expérience utilisateur.
Les tests de performance comprennent les quatre catégories suivantes:
- débit du binder (disponible dans
system/libhwbinder/vts/performance/Benchmark_binder.cpp
). - latence de liaison (disponible dans
frameworks/native/libs/binder/tests/schd-dbg.cpp
). - le débit du nœud de calcul (disponible dans
system/libhwbinder/vts/performance/Benchmark.cpp
). - Latence de hwbinder (disponible dans
system/libhwbinder/vts/performance/Latency.cpp
).
À propos de binder et de hwbinder
Le classeur et le hwbinder sont la communication inter-processus (IPC) Android d'infrastructures qui partagent le même pilote Linux, mais avec les éléments suivants : différences qualitatives:
Aspect | classeur | hwbinder |
---|---|---|
Objectif | Fournir un schéma d'IPC à usage général pour le framework | Communiquer avec le matériel |
Propriété | Optimisé pour l'utilisation du framework Android | Frais généraux minimaux et faible latence |
Modifier la règle de planification pour le premier plan/l'arrière-plan | Oui | Non |
Transmission d'arguments | Utilise la sérialisation compatible avec l'objet Parcel | Utilise des tampons de dispersion et évite la surcharge de la copie des données requises pour Sérialisation des parcelles |
Héritage de la priorité | Non | Oui |
Processus de liaison et de hwbinder
Un visualiseur Systrace affiche les transactions comme suit:
Dans l'exemple ci-dessus:
- Les quatre (4) processus schd-dbg sont des processus client.
- Les quatre (4) processus de liaison sont des processus de serveur (le nom commence par Liaison et se termine par un numéro de séquence).
- Un processus client est toujours associé à un processus serveur, qui est dédié à son client.
- Toutes les paires de processus client-serveur sont planifiées indépendamment par noyau simultanément.
Dans le processeur 1, le noyau du système d'exploitation exécute le client pour émettre la requête. Ensuite, utilise le même processeur chaque fois que possible pour activer un processus de serveur, gérer requête, puis revenez au contexte une fois la requête terminée.
Débit et latence
Dans une transaction parfaite, où les processus client et serveur changent les tests de débit et de latence ne produisent pas de résultats messages. Toutefois, lorsque le noyau du système d'exploitation traite une requête d'interruption, qu'il s'agisse du matériel, de l'attente de verrous ou simplement du choix de ne pas gérer un message immédiatement, une bulle de latence peut se former.
Le test de débit génère un grand nombre de transactions avec différentes les tailles de charge utile, ce qui fournit une bonne estimation de la durée normale de la transaction (dans (meilleurs scénarios) et le débit maximal que la liaison peut atteindre.
En revanche, le test de latence n'effectue aucune action sur la charge utile pour minimiser à l'heure normale de la transaction. Nous pouvons utiliser le temps de transaction pour estimer la liaison les frais généraux, faire des statistiques pour le pire des cas et calculer le ratio les transactions dont la latence respecte un délai spécifié.
Gérer les inversions de priorité
Une inversion de priorité se produit lorsqu'un thread de priorité supérieure est logiquement en attente d'un thread avec une priorité inférieure. Les applications en temps réel ont un problème d'inversion de priorité:
Lors de l'utilisation de la planification CFS (Completely Fair Scheduler) de Linux, un thread s'exécute toujours peut s'exécuter même lorsque d'autres threads ont une priorité plus élevée. Par conséquent, les applications avec planification CFS gèrent l'inversion de priorité comme le comportement attendu et non comme un problème. Dans les cas où le framework Android a besoin d'une planification en temps réel pour garantir le privilège des threads à priorité élevée, doit être résolu.
Exemple d'inversion de priorité lors d'une transaction de liaison (le thread RT est bloquée logiquement par d'autres threads SCP en attendant qu'un thread de liaison service):
Pour éviter les blocages, vous pouvez utiliser l'héritage des priorités afin d'escalader temporairement le problème du thread de liaison à un thread RT lorsqu'il traite une requête d'un client RT. N'oubliez pas que la planification en temps réel dispose de ressources limitées et doit être utilisée avec précaution. Dans un système avec n processeurs, le nombre maximal de processeurs en temps réel La valeur "threads" correspond également à n. d'autres threads en temps réel peuvent devoir patienter ne respectent pas leurs délais) si tous les processeurs sont occupés par d'autres threads RT.
Pour résoudre toutes les inversions de priorité possibles, vous pouvez utiliser l'héritage pour le binder et le hwbinder. Cependant, comme le binder est largement utilisé sur l'ensemble du système, l'activation de l'héritage de priorité pour les transactions de liaison peut de spammer le système avec plus de threads en temps réel qu'il ne peut en traiter.
Exécuter des tests de débit
Le test de débit est exécuté sur le débit de transaction de liaison/hwbinder. Dans un système non surchargé, les bulles de latence sont rares et leur impact peuvent être éliminées tant que le nombre d'itérations est suffisamment élevé.
- Le test de débit de binder est en cours
system/libhwbinder/vts/performance/Benchmark_binder.cpp
- Le test de débit hwbinder est en cours
system/libhwbinder/vts/performance/Benchmark.cpp
Résultats des tests
Exemple de résultats des tests de débit pour des transactions utilisant différentes charges utiles tailles:
Benchmark Time CPU Iterations --------------------------------------------------------------------- BM_sendVec_binderize/4 70302 ns 32820 ns 21054 BM_sendVec_binderize/8 69974 ns 32700 ns 21296 BM_sendVec_binderize/16 70079 ns 32750 ns 21365 BM_sendVec_binderize/32 69907 ns 32686 ns 21310 BM_sendVec_binderize/64 70338 ns 32810 ns 21398 BM_sendVec_binderize/128 70012 ns 32768 ns 21377 BM_sendVec_binderize/256 69836 ns 32740 ns 21329 BM_sendVec_binderize/512 69986 ns 32830 ns 21296 BM_sendVec_binderize/1024 69714 ns 32757 ns 21319 BM_sendVec_binderize/2k 75002 ns 34520 ns 20305 BM_sendVec_binderize/4k 81955 ns 39116 ns 17895 BM_sendVec_binderize/8k 95316 ns 45710 ns 15350 BM_sendVec_binderize/16k 112751 ns 54417 ns 12679 BM_sendVec_binderize/32k 146642 ns 71339 ns 9901 BM_sendVec_binderize/64k 214796 ns 104665 ns 6495
- Time indique le délai aller-retour mesuré en temps réel.
- Processeur indique le temps cumulé lors de la planification des processeurs pour le test.
- Les itérations indiquent le nombre de fois où la fonction de test exécuté.
Par exemple, pour une charge utile de 8 octets:
BM_sendVec_binderize/8 69974 ns 32700 ns 21296
... le débit maximal que la liaison peut atteindre est calculé comme suit:
Débit MAX avec une charge utile de 8 octets = (8 * 21296)/69974 ~= 2,423 b/ns ~= 2,268 Go/s
Options de test
Pour obtenir les résultats au format .json, exécutez le test avec la commande
Argument --benchmark_format=json
:
libhwbinder_benchmark --benchmark_format=json
{
"context": {
"date": "2017-05-17 08:32:47",
"num_cpus": 4,
"mhz_per_cpu": 19,
"cpu_scaling_enabled": true,
"library_build_type": "release"
},
"benchmarks": [
{
"name": "BM_sendVec_binderize/4",
"iterations": 32342,
"real_time": 47809,
"cpu_time": 21906,
"time_unit": "ns"
},
….
}
Exécuter des tests de latence
Le test de latence mesure le temps qu'il faut au client pour commencer initialiser la transaction, passer au processus serveur pour la gestion, pour recevoir le résultat. Le test recherche également les comportements de programmeur connus qui peut avoir un impact négatif sur la latence des transactions, par exemple avec un planificateur qui ne prendre en charge l'héritage des priorités ou respecter l'indicateur de synchronisation.
- Le test de latence de la liaison
frameworks/native/libs/binder/tests/schd-dbg.cpp
- Le test de latence du mécanisme de liaison est en cours
system/libhwbinder/vts/performance/Latency.cpp
Résultats des tests
Les résultats (au format .json) présentent des statistiques pour la latence moyenne, la meilleure/la pire et la le nombre d'échéances manquées.
Options de test
Les tests de latence utilisent les options suivantes:
Commande | Description |
---|---|
-i value |
Spécifiez le nombre d'itérations. |
-pair value |
Spécifiez le nombre de paires de processus. |
-deadline_us 2500 |
Indiquez la date limite en nous. |
-v |
Permet d'obtenir une sortie détaillée (débogage). |
-trace |
Interrompre la trace une fois le délai atteint. |
Les sections suivantes détaillent chaque option, décrivent l'utilisation et fournissent des exemples de résultats.
Spécifier des itérations
Exemple avec un grand nombre d'itérations et la sortie détaillée désactivée:
libhwbinder_latency -i 5000 -pair 3
{
"cfg":{"pair":3,"iterations":5000,"deadline_us":2500},
"P0":{"SYNC":"GOOD","S":9352,"I":10000,"R":0.9352,
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996},
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
},
"P1":{"SYNC":"GOOD","S":9334,"I":10000,"R":0.9334,
"other_ms":{ "avg":0.19, "wst":2.9 , "bst":0.055, "miss":2, "meetR":0.9996},
"fifo_ms": { "avg":0.16, "wst":3.1 , "bst":0.066, "miss":1, "meetR":0.9998}
},
"P2":{"SYNC":"GOOD","S":9369,"I":10000,"R":0.9369,
"other_ms":{ "avg":0.19, "wst":4.8 , "bst":0.055, "miss":6, "meetR":0.9988},
"fifo_ms": { "avg":0.15, "wst":1.8 , "bst":0.067, "miss":0, "meetR":1}
},
"inheritance": "PASS"
}
Ces résultats de test indiquent les éléments suivants:
"pair":3
- Crée une paire client-serveur.
"iterations": 5000
- Inclut 5 000 itérations.
"deadline_us":2500
- Le délai est 2 500us (2,5 ms). la plupart des transactions sont susceptibles de respecter ce .
"I": 10000
- Une seule itération de test comprend deux (2) transactions:
<ph type="x-smartling-placeholder">
- </ph>
- Une transaction par priorité normale (
CFS other
) - Une transaction par priorité en temps réel (
RT-fifo
)
- Une transaction par priorité normale (
"S": 9352
- 9 352 transactions sont synchronisées sur le même processeur.
"R": 0.9352
- Indique le ratio de synchronisation entre le client et le serveur avec le même processeur.
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996}
- La moyenne (
avg
), la pire (wst
) et la meilleure (bst
) pour toutes les transactions émises par un appelant de priorité normale. Deux transactionsmiss
la date limite, ce qui donne le ratio de conformité (meetR
) 0,9996 "fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
- Semblable à
other_ms
, mais pour les transactions émises par un client avec Prioritért_fifo
. Il est probable (mais pas obligatoire) quefifo_ms
a un meilleur résultat queother_ms
, avec des Valeursavg
etwst
, etmeetR
supérieure (la différence peut être encore plus importante avec la charge en arrière-plan).
Remarque:La charge en arrière-plan peut affecter le débit
et le tuple other_ms
dans le test de latence. Seuls les
fifo_ms
peut afficher des résultats similaires tant que le chargement en arrière-plan
avec une priorité inférieure à RT-fifo
.
Spécifier des valeurs de paire
Chaque processus client est associé à
un processus serveur dédié au client,
et chaque paire peut être programmée
indépendamment de n'importe quel CPU. Toutefois, le processeur
la migration ne doit pas avoir lieu pendant une transaction tant que l'indicateur SYNC est
honor
Vérifiez que le système n'est pas surchargé. Alors qu'une latence élevée dans un environnement
les résultats des tests pour un système surchargé ne sont pas utiles
des informations. Pour tester un système avec une pression plus élevée, utilisez -pair
#cpu-1
(ou -pair #cpu
avec précaution). Tester avec
-pair n
avec n > #cpu
surcharge
et génère des informations inutiles.
Spécifier les valeurs de délai
Après des tests approfondis de scénarios utilisateur (exécution du test de latence sur produit qualifié), nous avons déterminé que l'échéance à respecter était de 2,5 ms. Neuf pour les applications exigeant des exigences plus élevées (par exemple, 1 000 photos/seconde), la valeur du délai sera modifiée.
Spécifier une sortie détaillée
L'utilisation de l'option -v
affiche une sortie détaillée. Exemple :
libhwbinder_latency -i 1 -v
-------------------------------------------------- service pid: 8674 tid: 8674 cpu: 1 SCHED_OTHER 0-------------------------------------------------- main pid: 8673 tid: 8673 cpu: 1 -------------------------------------------------- client pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0-------------------------------------------------- fifo-caller pid: 8677 tid: 8678 cpu: 0 SCHED_FIFO 99 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 ??? 99-------------------------------------------------- other-caller pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 SCHED_OTHER 0
- Le thread de service est créé avec un
SCHED_OTHER
et l'exécuter dansCPU:1
avecpid 8674
. - La première transaction est ensuite lancée par
fifo-caller
Pour assurer le traitement de cette transaction, le mécanisme d'association met à niveau la priorité du serveur (pid: 8674 tid: 8676
) sur 99 et l'indique également avec une classe de planification temporaire (imprimée sous la forme???
). Le programmeur puis met le processus serveur dansCPU:0
pour s'exécuter et le synchronise avec même CPU avec son client. - L'appelant de la deuxième transaction a une
Priorité
SCHED_OTHER
. Le serveur revient à une version antérieure appelant avec une prioritéSCHED_OTHER
.
Utiliser la trace pour le débogage
Vous pouvez spécifier l'option -trace
pour déboguer les problèmes de latence. Quand ?
utilisé, le test de latence arrête l'enregistrement du tracelog au moment où
est détectée. Exemple :
atrace --async_start -b 8000 -c sched idle workq binder_driver sync freq
libhwbinder_latency -deadline_us 50000 -trace -i 50000 -pair 3
deadline triggered: halt ∓ stop trace log:/sys/kernel/debug/tracing/trace
Les composants suivants peuvent avoir un impact sur la latence:
- Mode de compilation Android Le mode Eng est généralement plus lent que mode débogage utilisateur.
- Framework : Comment le service de framework utilise-t-il
ioctl
pour configurer la liaison ? - Pilote de liaison. Le pilote accepte-t-il les contrôles le verrouillage ? Contient-il tous les correctifs de performance ?
- Version du noyau. Plus la capacité en temps réel du noyau est meilleurs sont les résultats.
- Configuration du noyau. La configuration du noyau contient-elle
Les configurations
DEBUG
telles queDEBUG_PREEMPT
etDEBUG_SPIN_LOCK
? - Programmeur de noyau. Le noyau dispose-t-il d’un
programmeur (EAS) ou HMP (Hétérogeneous Multi-Processing) ? N'importe quel noyau
chauffeurs (
cpu-freq
chauffeur,cpu-idle
conducteur,cpu-hotplug
, etc.) sur le planificateur ?