Configurazione RAM bassa RAM

Android supporta dispositivi con 512 MB di RAM. Questa documentazione ha lo scopo di aiutare gli OEM a ottimizzare e configurare il kernel Android 4.4 per i dispositivi con poca memoria. Molte di queste ottimizzazioni sono abbastanza generiche da poter essere applicate anche alle versioni precedenti.

Ottimizzazioni della piattaforma del kernel Android 4.4

Gestione migliorata della memoria

  • Configurazioni del kernel convalidate per il salvataggio della memoria: Swap to zram.
  • Arresta i processi memorizzati nella cache se stanno per essere rimossi dalla cache e sono troppo grandi.
  • Non consentire a servizi di grandi dimensioni di rientrare nella classificazione dei servizi A (in modo che non possano causare l'arresto del programma di avvio).
  • Arresta i processi (anche quelli normalmente inarrestabili come l'attuale IME) che diventano troppo grandi nella manutenzione inattiva.
  • Serializzare il lancio dei servizi in background.
  • Ottimizza l'utilizzo della memoria di dispositivi con poca RAM: livelli di regolazione della memoria esaurita (OOM) più stretti, cache grafiche più piccole.

Memoria di sistema ridotta

  • Rifilato system_server e processi di sistema di interfaccia utente (salvato diversi megabyte).
  • Cache dex precaricate in Dalvik (salvati diversi megabyte).
  • Opzione JIT-off convalidata (risparmia fino a 1,5 MB per processo).
  • Riduzione del sovraccarico della cache dei caratteri per processo.
  • Introdotto ArrayMap / ArraySet e ampiamente utilizzato in quadro come un sostituto più leggero-footprint per HashMap / HashSet .

Procstat

Aggiunta un'opzione per sviluppatori per mostrare lo stato della memoria e l'utilizzo della memoria dell'app classificati in base alla frequenza di esecuzione e alla quantità di memoria consumata.

API

Aggiunto ActivityManager.isLowRamDevice() per consentire applicazioni per rilevare se in esecuzione su dispositivi a bassa memoria e scegliere di disattivare funzioni di grandi dimensioni-RAM.

Tracciamento della memoria

Aggiunto HAL memtrack per tenere traccia delle allocazioni di memoria grafica, informazioni aggiuntive in dumpsys meminfo, riassunti chiarito in meminfo (per esempio, ha riferito RAM libera include RAM dei processi memorizzati nella cache, in modo che gli OEM non cercano di ottimizzare la cosa sbagliata).

Configurazione in fase di compilazione

Segnalazione dispositivo RAM insufficiente

ActivityManager.isLowRamDevice() indicatore determina se le applicazioni devono disattivare le funzioni che richiedono molta memoria specifici che opera in modo negativo su dispositivi a bassa memoria.

Per i 512 dispositivi MB, è previsto questo flag per tornare true . Può essere abilitato dalla seguente proprietà di sistema nel makefile del dispositivo.

PRODUCT_PROPERTY_OVERRIDES += ro.config.low_ram=true

Configurazioni di avvio

Il setup sfondo di default sul programma di avvio non dovrebbe usare carta da parati dal vivo. I dispositivi con poca memoria non dovrebbero preinstallare sfondi animati.

Configurazione del kernel

Ottimizzazione del kernel/ActivityManager per ridurre la richiesta diretta

Il recupero diretto si verifica quando un processo o il kernel tentano di allocare una pagina di memoria (direttamente o a causa di un errore in una nuova pagina) e il kernel ha utilizzato tutta la memoria libera disponibile. Ciò richiede che il kernel blocchi l'allocazione mentre libera una pagina. Questo a sua volta richiede spesso disco I / O di stanare una pagina di file-backed sporco o attendere lowmemorykiller per fermare un processo. Ciò può comportare un I/O aggiuntivo in qualsiasi thread, incluso un thread dell'interfaccia utente.

Per evitare di recupero diretta, il kernel ha filigrane che scatenano kswapd o di sfondo recupero. Questo è un thread che cerca di liberare pagine in modo che la prossima volta che un thread reale si alloca, può avere successo rapidamente.

La soglia predefinita per attivare il recupero in background è piuttosto bassa, circa 2 MB su un dispositivo da 2 GB e 636 KB su un dispositivo da 512 MB. Il kernel recupera solo pochi megabyte di memoria in background. Ciò significa che qualsiasi processo che alloca rapidamente più di pochi megabyte raggiungerà rapidamente il recupero diretto.

Il supporto per un kernel sintonizzabile è stato aggiunto nel ramo del kernel Android-3.4 come patch 92189d47f66c67e5fd92eafaa287e153197a454f ("aggiungi kbyte extra gratuito sintonizzabile"). Cherry-picking questa patch per il kernel di un dispositivo consente ActivityManager per dire al kernel per cercare di mantenere tre full-screen 32 buffer BPP di memoria libera.

Queste soglie possono essere configurate con il config.xml quadro.

<!-- Device configuration setting the /proc/sys/vm/extra_free_kbytes tunable
in the kernel (if it exists).  A high value will increase the amount of memory
that the kernel tries to keep free, reducing allocation time and causing the
lowmemorykiller to kill earlier.  A low value allows more memory to be used by
processes but may cause more allocations to block waiting on disk I/O or
lowmemorykiller.  Overrides the default value chosen by ActivityManager based
on screen size.  0 prevents keeping any extra memory over what the kernel keeps
by default.  -1 keeps the default. -->
<integer name="config_extraFreeKbytesAbsolute">-1</integer>
<!-- Device configuration adjusting the /proc/sys/vm/extra_free_kbytes
tunable in the kernel (if it exists).  0 uses the default value chosen by
ActivityManager.  A positive value  will increase the amount of memory that the
kernel tries to keep free, reducing allocation time and causing the
lowmemorykiller to kill earlier.  A negative value allows more memory to be
used by processes but may cause more allocations to block waiting on disk I/O
or lowmemorykiller.  Directly added to the default value chosen by
ActivityManager based on screen size. -->
<integer name="config_extraFreeKbytesAdjust">0</integer>

Tuning LowMemoryKiller

ActivityManager configura le soglie del LowMemoryKiller per abbinare la sua aspettativa di working set di pagine di file-backed (pagine nella cache) necessari per eseguire i processi in ciascun segmento livello di priorità. Se un dispositivo ha requisiti elevati per il working set, ad esempio se l'interfaccia utente del fornitore richiede più memoria o se sono stati aggiunti più servizi, le soglie possono essere aumentate.

Le soglie possono essere ridotte se viene riservata troppa memoria per le pagine supportate da file, in modo che i processi in background vengano eliminati molto prima che si verifichi il thrashing del disco a causa dell'eccessiva dimensione della cache.

<!-- Device configuration setting the minfree tunable in the lowmemorykiller
in the kernel.  A high value will cause the lowmemorykiller to fire earlier,
keeping more memory in the file cache and preventing I/O thrashing, but
allowing fewer processes to stay in memory.  A low value will keep more
processes in memory but may cause thrashing if set too low.  Overrides the
default value chosen by ActivityManager based on screen size and total memory
for the largest lowmemorykiller bucket, and scaled proportionally to the
smaller buckets.  -1 keeps the default. -->
<integer name="config_lowMemoryKillerMinFreeKbytesAbsolute">-1</integer>
<!-- Device configuration adjusting the minfree tunable in the
lowmemorykiller in the kernel.  A high value will cause the lowmemorykiller to
fire earlier, keeping more memory in the file cache and preventing I/O
thrashing, but allowing fewer processes to stay in memory.  A low value will
keep more processes in memory but may cause thrashing if set too low.  Directly
added to the default value chosen by          ActivityManager based on screen
size and total memory for the largest lowmemorykiller bucket, and scaled
proportionally to the smaller buckets. 0 keeps the default. -->
<integer name="config_lowMemoryKillerMinFreeKbytesAdjust">0</integer>

Passa a zram

zram swap può aumentare la quantità di memoria disponibile nel sistema comprimendo le pagine di memoria e inserendole in un'area di memoria di swap allocata dinamicamente. Questo scambia il tempo della CPU con un piccolo aumento di memoria, quindi considera questo fatto quando valuti l'impatto sulle prestazioni che uno scambio zram ha sul tuo sistema.

Android gestisce lo swap su zram a diversi livelli.

  • Innanzitutto, abilita queste opzioni del kernel per utilizzare efficacemente lo scambio zram:
    • CONFIG_SWAP
    • CONFIG_ZRAM
  • Aggiungere una riga simile a questa al vostro fstab:
    /dev/block/zram0 none swap defaults zramsize=<size in bytes>,swapprio=<swap partition priority>
    
    • zramsize è obbligatoria e indica la quantità di memoria non compresso desiderate che l'area zram di attesa. Puoi aspettarti rapporti di compressione nell'intervallo 30-50%.
    • swapprio è opzionale e solo per uso se si dispone di più di una zona di swap.

    Etichettare il dispositivo a blocchi associato come swap_block_device nelle specifiche del dispositivo sepolicy/file_contexts modo che sia trattata correttamente SELinux.

    /dev/block/zram0 u:object_r:swap_block_device:s0
    
  • Per impostazione predefinita, il kernel Linux scambia otto pagine di memoria alla volta. Quando si utilizza zram, il costo incrementale della lettura di una pagina alla volta è trascurabile e può essere d'aiuto se il dispositivo è sottoposto a un'estrema pressione della memoria. Per leggere una sola pagina alla volta, aggiungere la seguente al vostro init.rc :
    write /proc/sys/vm/page-cluster 0
    
  • Nella tua init.rc dopo la mount_all /fstab.X linea, aggiungere:
    swapon_all /fstab.X
    
  • I cgroup di memoria vengono configurati automaticamente all'avvio se la funzionalità è abilitata nel kernel.
  • Se cgroups memoria sono disponibili, ActivityManager contrassegni priorità inferiore fili come più swap di altri thread. Se è necessaria la memoria, il kernel Android inizia la migrazione pagine di memoria a zram di swap, dando una maggiore priorità alle pagine di memoria che sono state segnate da ActivityManager .

Ritagli, ioni e allocazione di memoria contigua (CMA)

Sui dispositivi con poca memoria, è importante prestare attenzione ai ritagli, specialmente quelli che non sono completamente utilizzati, come un ritaglio per la riproduzione video sicura. Esistono diverse soluzioni per ridurre al minimo l'impatto delle regioni ritagliate che dipendono dai requisiti esatti del tuo hardware.

Se l'hardware consente allocazioni di memoria discontinue, l'heap del sistema Ion consente allocazioni di memoria dalla memoria di sistema, eliminando la necessità di un carveout. Ion tenta anche di fare grandi allocazioni per eliminare la pressione del Translation Lookaside Buffer (TLB) sulle periferiche. Se le regioni di memoria devono essere contigue o limitate a un intervallo di indirizzi specifico, è possibile utilizzare il CMA.

Questo crea un ritaglio che il sistema può utilizzare anche per le pagine mobili. Quando l'area è necessaria, le pagine mobili vengono migrate da essa, consentendo al sistema di utilizzare un ampio carveout per altri scopi quando è libero. È possibile utilizzare CMA direttamente con l'heap Ion CMA.

Suggerimenti per l'ottimizzazione dell'app

Comprendere i vari stati dei processi in Android

Stato Senso Dettagli
SERVICE
SERVICE_RESTARTING
App eseguite in background per motivi relativi alle app. SERVICE SERVICE_RESTARTING sono i maggiori problemi comuni applicazioni hanno quando vengono eseguiti in background troppo. Usa durata% * pss o la durata% come "cattiveria" metrica. Idealmente, queste app non dovrebbero essere affatto in esecuzione.
IMPORTANT_FOREGROUND
RECEIVER
App in esecuzione in background (non interagiscono direttamente con l'utente). Questi aggiungono il carico di memoria al sistema. Utilizzare il (% Durata * PSS) Valore "cattiveria" per ordine questi processi. Tuttavia, molte di queste app vengono eseguite per buoni motivi. La dimensione di PSS è una parte importante del loro carico di memoria.
PERSISTENT Processo di sistema persistente. Traccia pss di guardare per questi processi diventando troppo grande.
TOP Il processo con cui l'utente sta attualmente interagendo. pss è l'importante metrica qui, mostrando quanto il carico di memoria l'applicazione crea durante l'uso.
HOME
CACHED_EMPTY
I processi che il sistema sta mantenendo nel caso in cui siano nuovamente necessari. Questi processi possono essere interrotti liberamente in qualsiasi momento e ricreati se necessario. Lo stato della memoria (normale, moderato, basso, critico) viene calcolato in base a quanti di questi processi sta eseguendo il sistema. La chiave metrica per questi processi è il PSS. In questo stato, questi processi riducono il più possibile i loro footprint di memoria, per consentire di mantenere il numero massimo totale di processi. In questo stato, un'applicazione ben educati ha in genere una significativamente più piccolo ingombro pss di quanto non faccia nella TOP Stato.
CACHED_ACTIVITY
CACHED_ACTIVITY_CLIENT
Quando confrontato con TOP , queste mostrano quanto bene un app rilascia la memoria in secondo piano. Esclusa CACHED_EMPTY stato rende questi dati meglio, perché elimina situazioni in cui il processo è avviato per alcune ragioni oltre interagire con l'utente. Questo elimina che trattano con l'interfaccia utente in testa CACHED_EMPTY ottiene quando le attività degli utenti connessi.

Analisi

Analisi del tempo di avvio dell'app

Per analizzare il tempo di avvio della tua applicazione, eseguire $ adb shell am start -P o --start-profiler e iniziare la vostra applicazione. Il profiler si avvia dopo che il processo è stato biforcato dallo zigote e prima che qualsiasi codice venga caricato nel fork.

Analizzare utilizzando le segnalazioni di bug

Segnalazioni di bug contengono diversi servizi, tra cui batterystats , netstats , procstats , e usagestats , che possono essere utilizzati per il debug. I report possono includere righe come questa:

------ CHECKIN BATTERYSTATS (dumpsys batterystats --checkin) ------
7,0,h,-2558644,97,1946288161,3,2,0,340,4183
7,0,h,-2553041,97,1946288161,3,2,0,340,4183

Verifica di eventuali processi persistenti

Per verificare la presenza di processi persistenti, riavvia il dispositivo e controlla i processi. Quindi, esegui il dispositivo per alcune ore e controlla nuovamente i processi. Non dovrebbero esserci processi di lunga durata tra i due controlli.

Esecuzione di test di longevità

Per eseguire test di longevità, eseguire il dispositivo per periodi più lunghi e tenere traccia della memoria dei processi per determinare se aumenta o rimane costante. Quindi crea casi d'uso canonici ed esegui test di longevità su questi scenari.