Questo documento fornisce ai partner indicazioni su come migliorare i tempi di avvio per Dispositivi Android Il tempo di avvio è un componente importante delle prestazioni del sistema Gli utenti devono attendere il completamento dell'avvio prima di poter utilizzare il dispositivo. Per i dispositivi come nel caso di auto in cui l'avvio a freddo avviene più spesso, il tempo è fondamentale (a nessuno piace aspettare decine di secondi solo per inserire destinazione di navigazione).
Android 8.0 consente di ridurre i tempi di avvio grazie al supporto di diversi miglioramenti in una serie di componenti. La tabella seguente riassume questo rendimento miglioramenti (misurati su dispositivi Google Pixel e Pixel XL).
Componente | Miglioramento |
---|---|
Bootloader |
|
Kernel del dispositivo |
|
Ottimizzazione I/O |
|
init.*.rc |
|
Animazione di avvio |
|
Criterio SELinux | 0,2 sec risparmiati da genfscon |
Ottimizza bootloader
Per ottimizzare il bootloader in modo da migliorare i tempi di avvio:
- Per il logging:
- Disattiva la scrittura dei log in UART perché può richiedere molto tempo e molti log. Sui dispositivi Google Pixel, abbiamo riscontrato che rallenta il bootloader di 1,5 secondi.
- Registra solo le situazioni di errore e valuta la possibilità di archiviare altre informazioni in memoria con un meccanismo separato per il recupero.
- Per la decompressione del kernel, considerare l'uso di LZ4 per l'hardware contemporaneo anziché GZIP (esempio patch). Tieni presente che opzioni di compressione del kernel diverse possono avere tempi di decompressione e alcune opzioni potrebbero funzionare meglio di altre per il tuo per uno specifico hardware.
- Controlla i tempi di attesa non necessari per il debouncing/l'accesso in modalità speciale e riduci a icona che li rappresentano.
- Passa il tempo di avvio nel bootloader nel kernel come cmdline.
- Controllare il clock della CPU e considerare il caricamento in contemporanea (richiede supporto multi-core) per il caricamento del kernel e l'inizializzazione di I/O.
Ottimizza l'efficienza dell'I/O
Migliorare l'efficienza di I/O è fondamentale per velocizzare i tempi di avvio e tutto ciò che non è necessario deve essere differito fino a dopo l'avvio (su Google Pixel, circa 1,2 GB di dati vengono letti all'avvio).
Ottimizza il file system
La lettura anticipata del kernel Linux si attiva quando un file viene letto dall'inizio o quando i blocchi vengono letti in sequenza, rendendo necessario l'ottimizzazione dello scheduler specifici per l'avvio (che ha un carico di lavoro diverso rispetto alle normali app).
I dispositivi che supportano aggiornamenti senza interruzioni (A/B) traggono un notevole vantaggio dal file system ottimizzazione al primo avvio (ad es. 20 secondi su Google Pixel). Per fare un esempio, abbiamo ottimizzato i seguenti parametri per 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 ...
Vari
- Attivare la dimensione di precaricamento dell'hash dm-verity utilizzando la configurazione del kernel DM_VERITY_HASH_PREFETCH_MIN_SIZE (la dimensione predefinita è 128).
- Per una migliore stabilità del file system e un controllo forzato eliminato che si verifica su ad ogni avvio, usa il nuovo strumento di generazione ext4 impostando TARGET_USES_MKE2FS in BoardConfig.mk.
Analizza I/O
Per comprendere le attività di I/O durante l'avvio, usa i dati ftrace del kernel (utilizzati anche systrace):
trace_event=block,ext4 in BOARD_KERNEL_CMDLINE
Per ripartire l'accesso ai file per ogni file, apporta le seguenti modifiche al kernel (solo kernel di sviluppo, non usare nei kernel di produzione):
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);
Utilizza i seguenti script per facilitare l'analisi delle prestazioni dell'avvio.
system/extras/boottime_tools/bootanalyze/bootanalyze.py
Misura il tempo di avvio con una suddivisione dei passaggi importanti del processo di avvio.system/extras/boottime_tools/io_analysis/check_file_read.py boot_trace
Fornisce informazioni di accesso per ogni file.system/extras/boottime_tools/io_analysis/check_io_trace_all.py boot_trace
Fornisce un'analisi a livello di sistema.
Ottimizza init.*.rc
L'inizializzazione è il bridge dal kernel fino a quando il framework non viene stabilito. i dispositivi in genere impiegano alcuni secondi in diverse fasi di avvio.
Esegui attività in parallelo
Anche se l'attuale inizializzazione di Android è più o meno un singolo processo in thread, può comunque eseguire alcune attività in parallelo.
- Eseguire comandi lenti in un servizio di script shell e unirlo in un secondo momento
in attesa di una proprietà specifica. Android 8.0 supporta questo caso d'uso con una nuova
Comando
wait_for_property
. - Identifica le operazioni lente in init. Il sistema registra il comando init
exec/wait_for_prop o qualsiasi azione che richiede molto tempo (in Android 8.0, qualsiasi comando
che impiega più di 50 ms). Ad esempio:
init: Command 'wait_for_coldboot_done' action=wait_for_coldboot_done returned 0 took 585.012ms
La revisione di questo log potrebbe indicare opportunità di miglioramento.
- Avvia i servizi e abilita in anticipo i dispositivi periferici sul percorso critico. Per Ad esempio, alcuni SOC richiedono di avviare i servizi relativi alla sicurezza prima SurfaceFlinger. Rivedi il log di sistema quando ServiceManager restituisce "wait for" " : di solito indica che è necessario avviare un servizio dipendente. per prima cosa.
- Rimuovi eventuali servizi e comandi inutilizzati in init.*.rc. Qualsiasi elemento non utilizzato in la fase iniziale di init deve essere rinviata al completamento dell'avvio.
Nota: il servizio immobiliare fa parte del processo di inizializzazione, quindi le chiamate
setproperty
durante l'avvio può causare un ritardo lungo se il comando init è occupato in
comandi integrati.
Usa l'ottimizzazione dello scheduler
Utilizza l'ottimizzazione dello scheduler per l'avvio anticipato. Esempio da 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
Alcuni servizi potrebbero richiedere un boost di priorità durante l'avvio. Esempio:
init.zygote64.rc: service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root ...
Inizia presto lo zigote
I dispositivi con crittografia basata su file possono avviare lo zigote prima (per impostazione predefinita, zygote viene lanciato nella classe main, che è molto più tardi di zygote-start). Quando esegui questa operazione, assicurati di consentire l'esecuzione di zygote in tutte le CPU (come l'impostazione del cpuset errata può forzare l'esecuzione dello zygote in CPU specifiche).
Disattiva risparmio energetico
Durante l'avvio del dispositivo, l'impostazione di risparmio energetico per componenti come UFS e/o CPU e il governatore può essere disattivato.
Attenzione:il risparmio energetico deve essere attivato in modalità di ricarica per maggiore efficienza.
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
Rimanda l'inizializzazione non critica
L'inizializzazione non critica, come la ZRAM, può essere differita a boot_complete
.
on property:sys.boot_completed=1 # Enable ZRAM on boot_complete swapon_all /vendor/etc/fstab.${ro.hardware}
Ottimizza animazione all'avvio
Utilizza i suggerimenti riportati di seguito per ottimizzare l'animazione all'avvio.
Configura avvio anticipato
Android 8.0 consente di avviare l'animazione all'avvio in anticipo, prima di montare i dati utente della partizione di testo. Tuttavia, anche quando si utilizza la nuova catena di strumenti ext4 in Android 8.0, fsck viene comunque attivata periodicamente per motivi di sicurezza, causando un ritardo nella avviando il servizio bootanimation.
Per fare in modo che bootanimation venga avviato prima, suddividi il montaggio fstab in due fasi:
- Nella fase iniziale, monta solo le partizioni (come
system/
evendor/
) che non richiedono l'esecuzione avvia i servizi di animazione all'avvio e le sue dipendenze (come servicemanager e Surfaceflinger). - Nella seconda fase, monta le partizioni (ad esempio
data/
) che non richiedono l'esecuzione di controlli.
L'animazione di avvio verrà avviata molto più velocemente (e in modo costante) indipendentemente caspita.
Termina pulizia
Dopo aver ricevuto il segnale di uscita, bootanimation riproduce l'ultima parte, la lunghezza che possono rallentare i tempi di avvio. Un sistema che si avvia rapidamente non richiede tempi lunghi animazioni che possono nascondere efficacemente eventuali miglioramenti apportati. I nostri suggerimenti rendendo sia il loop ripetuto che il finale corto.
Ottimizza SELinux
Utilizza i seguenti suggerimenti per ottimizzare SELinux per tempi di avvio migliori.
- Utilizza espressioni regolari chiare (regex). Regex non corretta
può comportare un overhead elevato durante la corrispondenza del criterio SELinux per
sys/devices
afile_contexts
. Ad esempio, l'espressione regolare/sys/devices/.*abc.*(/.*)?
forza erroneamente l'analisi di tutti/sys/devices
sottodirectory che contengono "abc", abilitando le corrispondenze sia per/sys/devices/abc
che per/sys/devices/xyz/abc
. Migliorare questa espressione regolare in/sys/devices/[^/]*abc[^/]*(/.*)?
attiva una corrispondenza solo per/sys/devices/abc
. - Sposta le etichette in genfscon. Questa funzionalità SELinux esistente passa i prefissi corrispondenti ai file nel kernel in il file binario SELinux, dove il kernel li applica ai file tra i file system. Ciò è utile anche per correggere errori di etichettatura dei file creati dal kernel, impedendo condizioni di gara che possono verificarsi tra i processi dello spazio utente che tentano di accedere prima della rietichettatura.
Strumenti e metodi
Per raccogliere dati per i target di ottimizzazione, utilizza i seguenti strumenti.
Grafico di avvio
Bootchart fornisce un'analisi del carico di CPU e I/O di tutti i processi dell'intero di un sistema operativo completo. Non richiede la ricreazione dell'immagine di sistema e può essere utilizzato come rapido dello stato di salute prima di immergersi in systrace.
Per attivare bootchart:
adb shell 'touch /data/bootchart/enabled'
adb reboot
Dopo l'avvio, recupera il grafico di avvio:
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
Al termine, elimina /data/bootchart/enabled
per impedire la raccolta
i dati ogni volta.
bootchart.png
non esiste, esegui
le seguenti:
- Esegui questi comandi:
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
- Aggiorna
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
per indirizzare alla copia locale dipybootchartgui
(si trova presso~/Documents/bootchart/pybootchartgui.py
)
Fioritura
Systrace consente di raccogliere tracce sia del kernel che di Android durante l'avvio. La visualizzazione di Systrace può aiutare ad analizzare un problema specifico durante il avvio automatico. (Tuttavia, per controllare il numero medio o il numero accumulato durante il durante l'intero avvio, è più facile esaminare direttamente la traccia del kernel).
Per abilitare systrace durante l'avvio:
- In
frameworks/native/cmds/atrace/atrace.rc
, modifica:write /sys/kernel/debug/tracing/tracing_on 0 write /sys/kernel/tracing/tracing_on 0
A:
# write /sys/kernel/debug/tracing/tracing_on 0 # write /sys/kernel/tracing/tracing_on 0
- Nel file
device.mk
, aggiungi la seguente riga:PRODUCT_PROPERTY_OVERRIDES += debug.atrace.tags.enableflags=802922 PRODUCT_PROPERTY_OVERRIDES += persist.traced.enable=0
- Nel file
BoardConfig.mk
del dispositivo, aggiungi quanto segue:BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug
- Nel file
init.rc
specifico per il dispositivo, aggiungi quanto segue: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
-
Dopo l'avvio, recupera la traccia:
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
Questa opzione attiva il tracciamento (disattivato per impostazione predefinita).
Per un'analisi I/O dettagliata, aggiungi anche block, ext4 e f2fs.