Ce document fournit des conseils aux partenaires afin d'améliorer les temps de démarrage pour des Appareils Android Le temps de démarrage est un composant important des performances du système, car les utilisateurs doivent attendre la fin du démarrage avant de pouvoir utiliser l’appareil. Pour les appareils comme les voitures où le démarrage à froid est plus fréquent, avec un démarrage rapide est essentiel (personne n'aime attendre des dizaines de secondes juste pour saisir une destination de navigation).
Android 8.0 permet de réduire les temps de démarrage grâce à plusieurs améliorations. sur toute une gamme de composants. Le tableau suivant récapitule ces performances (telles que mesurées sur les appareils Google Pixel et Pixel XL).
Component | Amélioration |
---|---|
Bootloader (chargeur d'amorçage) |
|
Noyau de l'appareil |
|
Réglage des E/S |
|
init.*.rc |
|
Animation au démarrage |
|
Règles SELinux | 0,2 seconde gagnée par genfscon |
Optimiser le bootloader
Pour optimiser le bootloader afin d'améliorer les temps de démarrage:
- Pour la journalisation:
<ph type="x-smartling-placeholder">
- </ph>
- Désactivez l'écriture de journaux dans UART, car l'opération peut prendre beaucoup de temps avec de nombreuses la journalisation. (Sur les appareils Google Pixel, nous avons constaté qu'il ralentit le bootloader 1,5 s.)
- Consigner uniquement les situations d'erreur et envisager de stocker d'autres informations en mémoire avec un mécanisme de récupération distinct.
- Pour la décompression du noyau, envisagez d'utiliser LZ4 pour le matériel contemporain. au lieu de GZIP (exemple : patch). Gardez à l'esprit que options de compression du noyau différentes peuvent avoir des chargements et des les temps de décompression, et certaines options peuvent être plus efficaces que d'autres à un matériel spécifique.
- Vérifiez les temps d'attente inutiles avant l'entrée en mode spécial/de rebond et réduisez de l'IA générative.
- Transmettez au noyau le temps de démarrage passé dans le bootloader en tant que cmdline.
- Vérifier l'horloge du processeur et envisager la parallélisation (nécessite une compatibilité multicœur) pour le chargement du noyau et l'initialisation des E/S.
Optimiser l'efficacité des E/S
L'amélioration de l'efficacité des E/S est essentielle pour accélérer le démarrage. tout ce qui n'est pas nécessaire doit être différé jusqu'à la fin du démarrage (sur un Google Pixel, environ 1,2 Go de données sont lus au démarrage).
Régler le système de fichiers
La lecture à l'avance du noyau Linux intervient lorsqu'un fichier est lu depuis le début ou les blocs sont lus de manière séquentielle, ce qui nécessite de régler le planificateur d'E/S spécifiquement pour le démarrage (qui a une charge de travail différente que les applications standards).
Les appareils compatibles avec les mises à jour fluides (A/B) bénéficient considérablement du système de fichiers réglage au premier démarrage (par exemple, 20 s sur Google Pixel). Par exemple, nous avons ajusté les paramètres suivants pour le Google Pixel:
on late-fs # boot time fs tune # boot time fs tune write /sys/block/sda/queue/iostats 0 write /sys/block/sda/queue/scheduler cfq write /sys/block/sda/queue/iosched/slice_idle 0 write /sys/block/sda/queue/read_ahead_kb 2048 write /sys/block/sda/queue/nr_requests 256 write /sys/block/dm-0/queue/read_ahead_kb 2048 write /sys/block/dm-1/queue/read_ahead_kb 2048 on property:sys.boot_completed=1 # end boot time fs tune write /sys/block/sda/queue/read_ahead_kb 512 ...
Divers
- Activer la taille de préchargement du hachage dm-verity à l'aide de la configuration du noyau DM_VERITY_HASH_PREFETCH_MIN_SIZE (la taille par défaut est 128).
- Pour une meilleure stabilité du système de fichiers et une vérification forcée abandonnée qui se produit sur à chaque démarrage, utilisez le nouvel outil de génération ext4 en définissant TARGET_USES_MKE2FS dans BoardConfig.mk.
Analyser les E/S
Pour comprendre les activités d'E/S au démarrage, utilisez les données ftrace du noyau (également utilisées par Systrace):
trace_event=block,ext4 in BOARD_KERNEL_CMDLINE
Pour répartir l'accès aux fichiers pour chaque fichier, apportez les modifications suivantes au noyau (noyau de développement uniquement, ne pas utiliser dans les noyaux de production):
diff --git a/fs/open.c b/fs/open.c index 1651f35..a808093 100644 --- a/fs/open.c +++ b/fs/open.c @@ -981,6 +981,25 @@ } EXPORT_SYMBOL(file_open_root); +static void _trace_do_sys_open(struct file *filp, int flags, int mode, long fd) +{ + char *buf; + char *fname; + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return; + fname = d_path(&filp-<f_path, buf, PAGE_SIZE); + + if (IS_ERR(fname)) + goto out; + + trace_printk("%s: open(\"%s\", %d, %d) fd = %ld, inode = %ld\n", + current-<comm, fname, flags, mode, fd, filp-<f_inode-<i_ino); +out: + kfree(buf); +} + long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) { struct open_flags op; @@ -1003,6 +1022,7 @@ } else { fsnotify_open(f); fd_install(fd, f); + _trace_do_sys_open(f, flags, mode, fd);
Utilisez les scripts suivants pour analyser les performances de démarrage.
system/extras/boottime_tools/bootanalyze/bootanalyze.py
Mesure le temps de démarrage avec le détail des étapes importantes du processus de démarrage.system/extras/boottime_tools/io_analysis/check_file_read.py boot_trace
Fournit des informations d'accès pour chaque fichier.system/extras/boottime_tools/io_analysis/check_io_trace_all.py boot_trace
Fournit une répartition au niveau du système.
Optimiser init.*.rc
Init est le pont entre le noyau jusqu’à ce que le framework soit établi, et les appareils passent généralement quelques secondes à différentes étapes d’initialisation.
Exécuter des tâches en parallèle
Bien que l'initialisation Android actuelle soit plus ou moins un processus monothread, peut toujours effectuer certaines tâches en parallèle.
- Exécutez des commandes lentes dans un service de script shell et joignez-les plus tard en
en attente d'une propriété spécifique. Android 8.0 prend en charge ce cas d'utilisation avec une nouvelle
wait_for_property
. - Identifiez les opérations lentes dans init. Le système consigne la commande init
exec/wait_for_prop ou toute action qui prend beaucoup de temps (sous Android 8.0, toute commande
en prenant plus de 50 ms). Par exemple:
init: Command 'wait_for_coldboot_done' action=wait_for_coldboot_done returned 0 took 585.012ms
L'examen de ce journal peut indiquer des possibilités d'amélioration.
- Démarrez les services et activez les périphériques dans le chemin critique le plus tôt possible. Pour Par exemple, certains SOC exigent de démarrer des services de sécurité SurfaceFlinger. Consulter le journal système lorsque ServiceManager renvoie "wait for service" — cela indique généralement qu'un service dépendant doit être démarré en premier.
- Supprimez tous les services et commandes inutilisés dans init.*.rc. Tout ce qui n'est pas utilisé dans l'initialisation préliminaire doit être reportée jusqu'à la fin du démarrage.
Remarque:Le service de propriétés fait partie du processus d'initialisation. Par conséquent, appeler
setproperty
au démarrage peut entraîner un long délai si init est occupé dans
commandes intégrées.
Utiliser le réglage du programmeur
Utiliser le réglage du programmeur pour le démarrage anticipé Exemple sur un Google Pixel:
on init # boottime stune write /dev/stune/schedtune.prefer_idle 1 write /dev/stune/schedtune.boost 100 on property:sys.boot_completed=1 # reset stune write /dev/stune/schedtune.prefer_idle 0 write /dev/stune/schedtune.boost 0 # or just disable EAS during boot on init write /sys/kernel/debug/sched_features NO_ENERGY_AWARE on property:sys.boot_completed=1 write /sys/kernel/debug/sched_features ENERGY_AWARE
Certains services peuvent nécessiter une optimisation de priorité au démarrage. Exemple :
init.zygote64.rc: service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root ...
Démarrer le zygote tôt
Les appareils équipés d'un chiffrement basé sur les fichiers peuvent démarrer zygote plus tôt au démarrage (par défaut, zygote est lancé au niveau de la classe main, ce qui est beaucoup plus tard que zygote-start). Lorsque vous procédez ainsi, assurez-vous d'autoriser zygote à s'exécuter dans tous les processeurs (comme un paramètre cpuset incorrect peut forcer zygote à s'exécuter dans des processeurs spécifiques).
Désactiver le mode d'économie d'énergie
Lors du démarrage de l'appareil, paramètre d'économie d'énergie pour les composants tels qu'UFS et/ou CPU peut être désactivé.
Attention:Activez le mode d'économie d'énergie dans pour plus d'efficacité.
on init # Disable UFS powersaving write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 0 write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 0 write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 0 write /sys/module/lpm_levels/parameters/sleep_disabled Y on property:sys.boot_completed=1 # Enable UFS powersaving write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 1 write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 1 write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 1 write /sys/module/lpm_levels/parameters/sleep_disabled N on charger # Enable UFS powersaving write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 1 write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 1 write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 1 write /sys/class/typec/port0/port_type sink write /sys/module/lpm_levels/parameters/sleep_disabled N
Reporter l'initialisation non critique
L'initialisation non critique telle que la ZRAM peut être différée vers boot_complete
.
on property:sys.boot_completed=1 # Enable ZRAM on boot_complete swapon_all /vendor/etc/fstab.${ro.hardware}
Optimiser l'animation au démarrage
Suivez les conseils ci-dessous pour optimiser l'animation au démarrage.
Configurer le démarrage anticipé
Android 8.0 permet de démarrer l'animation de démarrage plus tôt, avant d'installer les données utilisateur partition. Toutefois, même lorsque vous utilisez la nouvelle chaîne d'outils ext4 sous Android 8.0, fsck est déclenché périodiquement pour des raisons de sécurité, ce qui retarde pour démarrer le service bootanimation.
Pour que bootanimation démarre plus tôt, divisez le montage fstab en deux phases:
- Au cours de la phase initiale, installez uniquement les partitions (comme
system/
etvendor/
) qui ne nécessitent pas d'exécution puis démarrer les services d'animation et ses dépendances (comme servicemanager et surfaceflinger). - Dans la deuxième phase, installez des partitions (telles que
data/
) qui ne nécessitent pas de vérifications d'exécution.
L'animation au démarrage se lance beaucoup plus rapidement (et en continu), quel que soit fsck.
Terminer le nettoyage
Après avoir reçu le signal de sortie, bootanimation joue la dernière partie, la durée ce qui peut ralentir le démarrage. Un système qui démarre rapidement n'a pas besoin de longs des animations qui pourraient masquer efficacement les améliorations apportées. Nous vous recommandons en faisant à la fois la boucle répétée et la fin courte.
Optimiser SELinux
Utilisez les conseils suivants pour optimiser SELinux et améliorer les temps de démarrage.
- Utilisez des expressions régulières propres. Expression régulière incorrecte
peut entraîner de nombreux frais généraux lors de la mise en correspondance de la règle SELinux pour
sys/devices
dansfile_contexts
. Par exemple, l'expression régulière/sys/devices/.*abc.*(/.*)?
force par erreur une analyse de tous les/sys/devices
sous-répertoires contenant "abc", ce qui permet d'activer les correspondances pour/sys/devices/abc
et/sys/devices/xyz/abc
. Si vous améliorez cette expression régulière en/sys/devices/[^/]*abc[^/]*(/.*)?
activer une correspondance uniquement pour/sys/devices/abc
. - Déplacez les étiquettes vers genfscon. Cette fonctionnalité SELinux existante transmet les préfixes de correspondance de fichiers au noyau dans le binaire SELinux, où le noyau les applique aux fichiers systèmes de fichiers. Cela permet aussi de corriger les fichiers créés par le noyau mal étiquetés, ce qui empêche Conditions de concurrence pouvant se produire entre les processus d'espace utilisateur qui tentent d'accéder ces fichiers avant que le nouveau libellé n’ait lieu.
Outils et méthodes
Utilisez les outils suivants afin de collecter des données pour les objectifs d'optimisation.
Bootchart
Le graphique d'amorçage fournit la répartition de la charge du processeur et des E/S de tous les processus pour l'ensemble du système d'exploitation. Il ne nécessite pas de recompiler l'image système et peut être utilisé de l'intégrité avant de plonger dans Systrace.
Pour activer le bootchart, procédez comme suit:
adb shell 'touch /data/bootchart/enabled'
adb reboot
Après le démarrage, récupérez le graphique de démarrage:
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
Lorsque vous avez terminé, supprimez /data/bootchart/enabled
pour empêcher la collecte
les données à chaque fois.
bootchart.png
n'existe pas, faites
les éléments suivants:
<ph type="x-smartling-placeholder">- </ph>
- Exécutez les commandes suivantes:
sudo apt install python-is-python3
cd ~/Documents
git clone https://github.com/xrmx/bootchart.git
cd bootchart/pybootchartgui
mv main.py.in main.py
- Mettre à jour
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
pour pointer vers la copie locale depybootchartgui
(située à~/Documents/bootchart/pybootchartgui.py
)
Systrace
Systrace permet de collecter les traces du noyau et d'Android au démarrage. La visualisation de Systrace peut vous aider à analyser un problème spécifique pendant le au démarrage. Toutefois, pour vérifier le nombre moyen ou le nombre cumulé au cours de la au démarrage complet, il est plus facile d'examiner directement la trace du noyau).
Pour activer Systrace au démarrage:
- Dans
frameworks/native/cmds/atrace/atrace.rc
, remplacez:write /sys/kernel/debug/tracing/tracing_on 0 write /sys/kernel/tracing/tracing_on 0
À :
# write /sys/kernel/debug/tracing/tracing_on 0 # write /sys/kernel/tracing/tracing_on 0
- Dans le fichier
device.mk
, ajoutez la ligne suivante:PRODUCT_PROPERTY_OVERRIDES += debug.atrace.tags.enableflags=802922 PRODUCT_PROPERTY_OVERRIDES += persist.traced.enable=0
- Dans le fichier
BoardConfig.mk
de l'appareil, ajoutez ce qui suit:BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug
- Dans le fichier
init.rc
spécifique à l'appareil, ajoutez le code suivant:on property:sys.boot_completed=1 // This stops tracing on boot complete write /d/tracing/tracing_on 0 write /d/tracing/events/ext4/enable 0 write /d/tracing/events/f2fs/enable 0 write /d/tracing/events/block/enable 0
-
Après le démarrage, récupérez la trace:
adb root && adb shell atrace --async_stop -z -c -o /data/local/tmp/boot_trace
adb pull /data/local/tmp/boot_trace
$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py --from-file=boot_trace
Cela active le traçage (qui est désactivé par défaut).
Pour une analyse détaillée des E/S, ajoutez également le bloc, ainsi que ext4 et f2fs.