16 kB dimensione pagina

La dimensione della pagina è la granularità con cui un sistema operativo gestisce la memoria. La maggior parte delle CPU oggi supporta una dimensione di pagina di 4 KB, pertanto il sistema operativo e le app Android sono stati storicamente sviluppati e ottimizzati per funzionare con una dimensione di pagina di 4 KB. Le CPU ARM supportano la dimensione pagina più grande di 16 KB e, a partire da Android 15, AOSP supporta anche la compilazione di Android con una dimensione pagina di 16 KB. Questa opzione utilizza memoria aggiuntiva, ma migliora le prestazioni del sistema. A partire da Android 15, questa opzione non è attivata per impostazione predefinita, ma è disponibile come modalità sviluppatore o come opzione sviluppatore per consentire a OEM e sviluppatori di app di prepararsi al passaggio alla modalità 16 KB in futuro.

Android 15 e versioni successive supportano la compilazione di Android con un allineamento ELF di 16 KB, che funziona con kernel di 4 KB e 16 KB a partire da android14-6.1. Se utilizzata con un kernel di 16 KB, questa configurazione utilizza memoria aggiuntiva, ma migliora le prestazioni del sistema.

Impostare lo spazio utente di Android su 16 KB

Le pagine da 16 KB sono supportate solo sui target arm64 con kernel da 16 KB. Tuttavia, è disponibile anche un'opzione per simulare uno spazio utente di 16 KB su x86_64 per Cuttlefish.

Per i target arm64, se utilizzi Kleaf per compilare il kernel, --page_size=16k compila il kernel in modalità 16 KB. Se utilizzi direttamente la configurazione del kernel di Linux, puoi selezionare pagine di 16 KB impostando CONFIG_ARM64_16K_PAGES anziché CONFIG_ARM64_4K_PAGES.

Per attivare il supporto delle dimensioni di pagina di 16 KB nello spazio utente di Android, imposta le seguenti opzioni di compilazione sul tuo prodotto:

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true rimuove la definizione PAGE_SIZE e consente ai componenti di determinare le dimensioni della pagina in fase di runtime.
  • PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384 che garantisce che i file ELF della piattaforma vengano compilati con un allineamento di 16 KB. Queste dimensioni maggiori del necessario sono per la compatibilità futura. Con l'allineamento ELF a 16 KB, il kernel può supportare dimensioni di pagina di 4 KB/16 KB.

Verifica i flag di compilazione

Dopo aver selezionato il target lunch, verifica che i flag di compilazione siano configurati correttamente nell'ambiente:

$ source build/envsetup.sh
$ lunch target

$ get_build_var TARGET_MAX_PAGE_SIZE_SUPPORTED
16384
$ get_build_var TARGET_NO_BIONIC_PAGE_SIZE_MACRO
true

Se i due comandi precedenti restituiscono rispettivamente 16384 e true, i flag di compilazione sono configurati correttamente per funzionare con un kernel di 16 KB. Tuttavia, anche se una compilazione supera i controlli, potrebbero verificarsi problemi di runtime a causa delle differenze in un ambiente di 16 KB.

Programmazione di sistema con dimensioni pagina di 16 KB

La maggior parte del codice su qualsiasi dispositivo Android non gestisce direttamente le dimensioni delle pagine. Tuttavia, per il codice che gestisce le pagine, il comportamento di allocazione della memoria del kernel cambia e devi tenerlo presente per scrivere codice non solo compatibile, ma anche con il massimo rendimento e con un utilizzo minimo delle risorse.

Se chiami mmap in una regione di 1 KB, 2 KB o fino a 4 KB su un sistema di 4 KB, il sistema riserva 4 KB per l'implementazione. In altre parole, quando richiedi memoria al kernel, il kernel deve sempre arrotondare la memoria richiesta al valore superiore più vicino per le dimensioni della pagina. Ad esempio, se assegni una regione di 5 KB a una regione di 4 KB, il kernel assegna 8 KB.

Con un kernel di 16 KB, queste "code" aggiuntive delle pagine sono più grandi. Ad esempio, tutte queste allocazioni, da 1 KB a 5 KB, allocate 16 KB se utilizzate con un kernel da 16 KB. Se richiedi 17 KB, vengono allocati 32 KB.

Ad esempio, in un sistema di 4 KB, è possibile allocare due regioni anonime di lettura/scrittura di 4 KB. Tuttavia, su un kernel da 16 KB, ciò comporterebbe l'allocazione di due pagine o 32 KB. Su un kernel da 16 KB, se possibile, queste regioni possono essere combinate in un'unica pagina scrivibile o leggibile in modo da utilizzare solo 16 KB, sprecando 8 KB rispetto al caso del kernel da 4 KB. Per ridurre ulteriormente l'utilizzo della memoria, è possibile combinare più pagine. Infatti, su un sistema ottimizzato al massimo da 16 KB, le pagine da 16 KB richiedono meno memoria rispetto ai sistemi da 4 KB perché la tabella delle pagine è pari a un quarto della dimensione per la stessa memoria.

Ogni volta che utilizzi mmap, assicurati di arrotondare le dimensioni richieste per ottenere le dimensioni della pagina più vicine. In questo modo, l'intera quantità di memoria allocata dal kernel è direttamente visibile allo spazio utente nei valori di runtime, anziché essere richiesta implicitamente e accessibile implicitamente o accidentalmente.

Crea librerie condivise con allineamento ELF di 16 KB

Per compilare le librerie condivise che fanno parte del progetto Android, le impostazioni precedenti in Attiva dimensione pagina 16 KB sono sufficienti:

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
  • PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384

Per compilare librerie condivise che non fanno parte del progetto Android, devi passare questo flag del linker:

-Wl,-z,max-page-size=16384

Verificare i file binari e precompilati per l'allineamento ELF a 16 KB

Il modo migliore per verificare l'allineamento e il comportamento di runtime è testare ed eseguire su un kernel compilato di 16 KB. Tuttavia, per rilevare alcuni problemi in anticipo:

  • A partire da Android 16 (AOSP sperimentale), puoi impostare PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true in fase di compilazione. Utilizza ignore_max_page_size: true in Android.bp e LOCAL_IGNORE_MAX_PAGE_SIZE := true in Android.mk per ignorarli temporaneamente. Queste impostazioni verificano tutti i precompilati e ti consentono di rilevare quando uno viene aggiornato, ma non è allineato a 16 KB.

  • Puoi eseguire atest elf_alignment_test, che verifica l'allineamento dei file ELF on-device sui dispositivi lanciati con Android 15 e versioni successive.