In diesem Dokument finden Partner Hinweise zur Verbesserung der Bootzeiten für bestimmte Android-Geräte. Die Bootzeit ist ein wichtiger Bestandteil der Systemleistung, da Nutzer warten müssen, bis der Bootvorgang abgeschlossen ist, bevor sie das Gerät verwenden können. Bei Geräten wie Autos, bei denen das Kaltstarten häufiger vorkommt, ist eine kurze Startzeit entscheidend. Niemand möchte mehrere Dutzend Sekunden warten müssen, nur um ein Navigationsziel einzugeben.
Android 8.0 ermöglicht kürzere Bootzeiten, da mehrere Verbesserungen an verschiedenen Komponenten unterstützt werden. In der folgenden Tabelle sind diese Leistungsverbesserungen zusammengefasst (gemessen auf Google Pixel und Google Pixel XL).
Komponente | Verbesserung |
---|---|
Bootloader |
|
Gerätekernel |
|
I/O-Optimierung |
|
init.*.rc |
|
Boot-Animation |
|
SELinux-Richtlinie | 0,2 Sekunden durch genfscon gespart |
Bootloader optimieren
So optimieren Sie den Bootloader für kürzere Bootzeiten:
- Für die Protokollierung:
- Deaktivieren Sie das Schreiben von Protokollen in UART, da dies bei vielen Protokollen sehr lange dauern kann. (Auf Google Pixel-Geräten wurde festgestellt, dass dadurch der Bootloader um 1,5 Sekunden verlangsamt wird.)
- Protokollieren Sie nur Fehlersituationen und speichern Sie andere Informationen mit einem separaten Mechanismus zum Abrufen im Arbeitsspeicher.
- Für die Kerneldekomprimierung sollten Sie auf aktueller Hardware LZ4 anstelle von GZIP verwenden (Beispiel Patch). Beachten Sie, dass verschiedene Kernelkomprimierungsoptionen unterschiedliche Lade- und Dekomprimierungszeiten haben können. Außerdem funktionieren einige Optionen für Ihre spezifische Hardware möglicherweise besser als andere.
- Prüfen Sie unnötige Wartezeiten für das Entprellen/den Eintritt in den Sondermodus und minimieren Sie sie.
- Übergeben Sie die im Bootloader verbrachte Bootzeit als cmdline an den Kernel.
- Prüfen Sie die CPU-Taktfrequenz und ziehen Sie eine Parallelisierung (erfordert Multi-Core-Unterstützung) für das Laden des Kernels und das Initialisieren der E/A in Betracht.
E/A-Effizienz optimieren
Die Verbesserung der E/A-Effizienz ist entscheidend, um die Bootzeit zu verkürzen. Nicht notwendige Daten sollten erst nach dem Start gelesen werden. Auf einem Google Pixel werden beim Start etwa 1,2 GB an Daten gelesen.
Dateisystem optimieren
Die Vorab-Lesefunktion des Linux-Kernels wird aktiviert, wenn eine Datei von Anfang an gelesen wird oder Blöcke sequenziell gelesen werden. Daher müssen die I/O-Scheduler-Parameter speziell für das Booten optimiert werden, da das eine andere Arbeitslastcharakteristik als normale Apps hat.
Geräte, die nahtlose (A/B)-Updates unterstützen, profitieren beim ersten Start erheblich von der Optimierung des Dateisystems (z.B. 20 Sekunden bei Google Pixel). Als Beispiel haben wir die folgenden Parameter für Google Pixel optimiert:
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 ...
Sonstiges
- Aktivieren Sie die Größe des dm-verity-Hash-Prefetch mit der Kernelkonfiguration DM_VERITY_HASH_PREFETCH_MIN_SIZE (Standardgröße ist 128).
- Für eine bessere Dateisystemstabilität und eine entfallene erzwungene Prüfung, die bei jedem Start ausgeführt wird, verwenden Sie das neue Tool zum Erstellen von ext4-Dateisystemen. Legen Sie dazu in BoardConfig.mk TARGET_USES_MKE2FS fest.
E/A analysieren
Verwenden Sie Kernel-ftrace-Daten (auch von systrace verwendet), um I/O-Aktivitäten während des Bootens zu analysieren:
trace_event=block,ext4 in BOARD_KERNEL_CMDLINE
Nehmen Sie die folgenden Änderungen am Kernel vor, um den Dateizugriff für jede Datei aufzuschlüsseln (nur Entwicklungskernel; nicht in Produktionskerneln verwenden):
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);
Mit den folgenden Scripts können Sie die Bootleistung analysieren.
system/extras/boottime_tools/bootanalyze/bootanalyze.py
Misst die Bootzeit mit einer Aufschlüsselung der wichtigen Schritte im Bootvorgang.system/extras/boottime_tools/io_analysis/check_file_read.py boot_trace
Enthält Zugriffsinformationen für jede Datei.system/extras/boottime_tools/io_analysis/check_io_trace_all.py boot_trace
Eine Aufschlüsselung auf Systemebene.
init.*.rc optimieren
Init ist die Brücke vom Kernel bis zur Einrichtung des Frameworks. Geräte verbringen in der Regel einige Sekunden in verschiedenen Init-Phasen.
Aufgaben parallel ausführen
Die aktuelle Android-init ist zwar mehr oder weniger ein einzeiliger Prozess, Sie können aber einige Aufgaben parallel ausführen.
- Langsame Befehle in einem Shell-Script-Dienst ausführen und später darauf warten, dass eine bestimmte Property erfüllt ist. Android 8.0 unterstützt diesen Anwendungsfall mit einem neuen Befehl
wait_for_property
. - Langsame Vorgänge in init identifizieren Das System protokolliert den Befehl „init exec/wait_for_prop“ oder jede Aktion, die lange dauert (unter Android 8.0 jeder Befehl, der länger als 50 ms dauert). Beispiel:
init: Command 'wait_for_coldboot_done' action=wait_for_coldboot_done returned 0 took 585.012ms
Die Prüfung dieses Protokolls kann Verbesserungsmöglichkeiten aufzeigen.
- Starten Sie Dienste und aktivieren Sie Peripheriegeräte im kritischen Pfad frühzeitig. So müssen beispielsweise bei einigen SOCs sicherheitsrelevante Dienste gestartet werden, bevor SurfaceFlinger gestartet wird. Sehen Sie sich das Systemprotokoll an, wenn der ServiceManager „Warten auf Dienst“ zurückgibt. Dies ist in der Regel ein Zeichen dafür, dass ein abhängiger Dienst zuerst gestartet werden muss.
- Entfernen Sie alle nicht verwendeten Dienste und Befehle in init.*.rc. Alles, was in der frühen Phase der Initialisierung nicht verwendet wird, sollte bis zum Abschluss des Bootens verschoben werden.
Hinweis:Der Property-Dienst ist Teil des Init-Prozesses. Wenn Sie setproperty
während des Bootens aufrufen, kann es zu einer langen Verzögerung kommen, wenn Init in den integrierten Befehlen beschäftigt ist.
Scheduler-Optimierung verwenden
Verwenden Sie die Scheduler-Optimierung für einen schnellen Start. Beispiel von 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
Einige Dienste benötigen beim Starten möglicherweise eine höhere Priorität. Beispiel:
init.zygote64.rc: service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root ...
Zygote früh starten
Auf Geräten mit dateibasierter Verschlüsselung kann der Zygote früher beim Trigger „zygote-start“ gestartet werden. Standardmäßig wird der Zygote bei „class main“ gestartet, was viel später als „zygote-start“ ist. Achten Sie dabei darauf, dass der Zygote auf allen CPUs ausgeführt werden darf, da er bei einer falschen cpuset-Einstellung möglicherweise auf bestimmten CPUs ausgeführt wird.
Energiesparmodus deaktivieren
Während des Startens des Geräts können die Energiespareinstellungen für Komponenten wie UFS und/oder CPU-Taktregler deaktiviert werden.
Achtung:Im Lademodus sollte der Energiesparmodus aktiviert sein, um effizient zu arbeiten.
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
Nicht kritische Initialisierung verschieben
Nicht kritische Initialisierungen wie ZRAM können auf boot_complete
verschoben werden.
on property:sys.boot_completed=1 # Enable ZRAM on boot_complete swapon_all /vendor/etc/fstab.${ro.hardware}
Bootanimation optimieren
Mit den folgenden Tipps können Sie die Bootanimation optimieren.
Frühzeitigen Start konfigurieren
Unter Android 8.0 kann die Bootanimation schon gestartet werden, bevor die userdata-Partition bereitgestellt wird. Auch wenn die neue ext4-Tool-Chain in Android 8.0 verwendet wird, wird fsck aus Sicherheitsgründen weiterhin regelmäßig ausgelöst, was zu einer Verzögerung beim Starten des Bootanimationsdiensts führt.
Damit die Bootanimation frühzeitig gestartet wird, teilen Sie die Bereitstellung über die Datei „fstab“ in zwei Phasen auf:
- In der Anfangsphase sollten Sie nur die Partitionen bereitstellen (z. B.
system/
undvendor/
), für die keine Ausführungsüberprüfungen erforderlich sind. Starten Sie dann die Boot-Animationen und die zugehörigen Abhängigkeiten (z. B. servicemanager und surfaceflinger). - In der zweiten Phase werden Partitionen wie
data/
bereitgestellt, für die Laufzeitprüfungen erforderlich sind.
Die Boot-Animation wird unabhängig von fsck viel schneller (und in konstanter Zeit) gestartet.
Finish clean
Nach Erhalt des Beendigungssignals wird der letzte Teil der Bootanimation abgespielt. Die Länge dieses Teils kann die Bootzeit verlängern. Bei einem System, das schnell startet, sind keine langen Animationen erforderlich, die eventuelle Verbesserungen verdecken könnten. Wir empfehlen, sowohl die sich wiederholende Schleife als auch das Finale kurz zu halten.
SELinux optimieren
Mit den folgenden Tipps können Sie SELinux für kürzere Bootzeiten optimieren.
- Verwenden Sie saubere reguläre Ausdrücke (Regex). Unzureichend formatierte reguläre Ausdrücke können zu viel Overhead führen, wenn die SELinux-Richtlinie für
sys/devices
infile_contexts
abgeglichen wird. Beispiel: Der reguläre Ausdruck/sys/devices/.*abc.*(/.*)?
erzwingt fälschlicherweise einen Scan aller/sys/devices
-Unterverzeichnisse, die „abc“ enthalten, sodass sowohl/sys/devices/abc
als auch/sys/devices/xyz/abc
übereinstimmen. Wenn Sie diesen regulären Ausdruck zu/sys/devices/[^/]*abc[^/]*(/.*)?
verbessern, wird nur eine Übereinstimmung für/sys/devices/abc
aktiviert. - Verschieben Sie Labels zu genfscon. Diese vorhandene SELinux-Funktion übergibt Dateiabgleichspräfixe in der SELinux-Binärdatei an den Kernel, wo sie auf vom Kernel generierte Dateisysteme angewendet werden. Außerdem können so falsch beschriftete vom Kernel erstellte Dateien korrigiert werden, um Race-Zustände zu verhindern, die zwischen Userspace-Prozessen auftreten können, die versuchen, auf diese Dateien zuzugreifen, bevor die Neubeschriftung erfolgt.
Tools und Methoden
Mit den folgenden Tools können Sie Daten für Optimierungsziele erheben.
Bootchart
Bootchart bietet eine Aufschlüsselung der CPU- und E/A-Auslastung aller Prozesse für das gesamte System. Es ist nicht erforderlich, das System-Image neu zu erstellen, und es kann als Schnellüberprüfung verwendet werden, bevor Sie sich mit systrace befassen.
So aktivieren Sie „bootchart“:
adb shell 'touch /data/bootchart/enabled'
adb reboot
Nach dem Starten das Boot-Diagramm abrufen:
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
Wenn Sie fertig sind, löschen Sie /data/bootchart/enabled
, damit die Daten nicht jedes Mal erfasst werden.
bootchart.png
nicht vorhanden ist, gehen Sie so vor:
- Führen Sie folgende Befehle aus:
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
- Aktualisieren Sie
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
, sodass es auf die lokale Kopie vonpybootchartgui
(~/Documents/bootchart/pybootchartgui.py
) verweist.
Systrace
Mit Systrace können Sie sowohl Kernel- als auch Android-Traces während des Bootens erfassen. Die Visualisierung von systrace kann bei der Analyse eines bestimmten Problems beim Starten helfen. Wenn Sie jedoch die durchschnittliche Anzahl oder die Gesamtzahl während des gesamten Bootvorgangs prüfen möchten, ist es einfacher, direkt in den Kernel-Trace zu schauen.
So aktivieren Sie systrace beim Starten:
- Ändern Sie in
frameworks/native/cmds/atrace/atrace.rc
Folgendes:write /sys/kernel/debug/tracing/tracing_on 0 write /sys/kernel/tracing/tracing_on 0
Sie haben folgende Optionen:
# write /sys/kernel/debug/tracing/tracing_on 0 # write /sys/kernel/tracing/tracing_on 0
- Fügen Sie in der Datei
device.mk
die folgende Zeile hinzu:PRODUCT_PROPERTY_OVERRIDES += debug.atrace.tags.enableflags=802922 PRODUCT_PROPERTY_OVERRIDES += persist.traced.enable=0
- Fügen Sie in der Datei
BoardConfig.mk
des Geräts Folgendes hinzu:BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug
- Fügen Sie in der gerätespezifischen
init.rc
-Datei Folgendes hinzu: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
-
Nach dem Starten den Ablauf erfassen:
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
Dadurch wird das Tracing aktiviert, das standardmäßig deaktiviert ist.
Für eine detaillierte I/O-Analyse fügen Sie auch „block“, „ext4“ und „f2fs“ hinzu.