Optimiser les temps de démarrage

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)
  • Économie de 1,6 s en supprimant le journal UART
  • Vous avez gagné 0,4 s en passant de GZIP à LZ4
Noyau de l'appareil
  • Économie de 0,3 seconde grâce à la suppression des configurations de noyau inutilisées et à la réduction de la taille du pilote
  • 0,3 s gagné grâce à l'optimisation du préchargement dm-verity
  • Gain de 0,15 s pour supprimer l'attente/le test inutiles dans le pilote
  • Vous avez gagné 0,12 s pour supprimer CONFIG_CC_OPTIMIZE_FOR_SIZE
Réglage des E/S
  • 2 s gagnées au démarrage normal
  • 25 s gagnées au premier démarrage
init.*.rc
  • 1,5 seconde gagnée grâce à la mise en parallèle des commandes init
  • Vous avez gagné 0,25 s en démarrant zygote plus tôt
  • 0,22 s gagné grâce à la configuration de cpuset
Animation au démarrage
  • Démarré 2 s plus tôt au démarrage sans déclenchement fsck, beaucoup plus grand au démarrage avec démarrage déclenché par fsck
  • 5 s gagnées sur le Pixel XL avec l'arrêt immédiat de l'animation de 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/ et vendor/) 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 dans file_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.

Si le bootchart ne fonctionne pas et que vous obtenez un message d'erreur indiquant que bootchart.png n'existe pas, faites les éléments suivants: <ph type="x-smartling-placeholder">
    </ph>
  1. 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
        
  2. Mettre à jour $ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh pour pointer vers la copie locale de pybootchartgui (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
  • Cela active le traçage (qui est désactivé par défaut).

  • 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
  • Pour une analyse détaillée des E/S, ajoutez également le bloc, ainsi que ext4 et f2fs.

  • 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
    
<ph type="x-smartling-placeholder">