Compatible avec les tailles de page de 16 ko

Historiquement, Android n'a pris en charge que les tailles de page de mémoire de 4 Ko, ce qui a optimisé les performances de la mémoire système pour la quantité moyenne de mémoire totale dont les appareils Android disposent généralement. À partir d'Android 15, AOSP est compatible avec les appareils configurés pour utiliser une taille de page de 16 ko (appareils 16 ko). Si votre application utilise des bibliothèques NDK, directement ou indirectement via un SDK, vous devrez la recompiler pour qu'elle fonctionne sur ces appareils de 16 Ko.

Alors que les fabricants d'appareils continuent de concevoir des appareils avec de plus grandes quantités de mémoire physique (RAM), beaucoup de ces appareils adopteront des tailles de page de 16 Ko (et éventuellement plus) pour optimiser les performances de l'appareil. L'ajout de la prise en charge des appareils avec une taille de page de 16 ko permet à votre application de s'exécuter sur ces appareils et de bénéficier des améliorations de performances associées. Sans recompilation, les applications ne fonctionneront pas sur les appareils 16 Ko dans les futures versions d'Android.

Pour vous aider à ajouter la compatibilité avec votre application, nous vous avons fourni des conseils sur la façon de vérifier si votre application est concernée, de recompiler votre application (le cas échéant) et de tester votre application dans un environnement de 16 ko à l'aide d'émulateurs (y compris les images système Android 15 pour Android Emulator).

Exigence de compatibilité avec Google Play

Pour s'assurer que votre application fonctionne correctement sur les dernières versions d'Android, toutes les applications ciblant Android 15 (niveau d'API 35) et versions ultérieures doivent être compatibles avec les tailles de page de mémoire de 16 Ko sur les appareils 64 bits sur Google Play. À partir du 1er février 2027, si les mises à jour de votre appli ne sont pas compatibles avec les tailles de page de mémoire de 16 ko, vous ne pourrez pas les publier.

Avertissement dans la console Google Play indiquant que les mises à jour des applications doivent prendre en charge les tailles de page de mémoire de 16 ko d'ici le 1er février 2027
Figure 1. Avertissement de compatibilité de la Google Play Console.

Avantages et gains de performances

Les appareils configurés avec une taille de page de 16 Ko utilisent un peu plus de mémoire en moyenne, mais bénéficient également de diverses améliorations des performances pour le système et les applications:

  • Temps de lancement des applications plus courts lorsque le système est soumis à une pression de mémoire: 3,16 % de moins en moyenne, avec des améliorations plus importantes (jusqu'à 30%) pour certaines applications que nous avons testées
  • Consommation d'énergie réduite au démarrage de l'application: réduction de 4,56% en moyenne
  • Lancement plus rapide de l'appareil photo: démarrage à chaud 4,48% plus rapide en moyenne et démarrage à froid 6,60% plus rapide en moyenne
  • Amélioration du temps de démarrage du système: 8% (environ 950 millisecondes) en moyenne

Ces améliorations sont basées sur nos premiers tests. Les résultats sur les appareils réels seront probablement différents. Nous fournirons une analyse supplémentaire des gains potentiels pour les applications à mesure que nous poursuivrons nos tests.

Vérifier si votre application est concernée

Si votre application utilise du code natif, vous devez la reconstruire pour qu'elle soit compatible avec les appareils de 16 ko. Si vous n'êtes pas sûr que votre application utilise du code natif, vous pouvez utiliser l'analyseur d'APK pour identifier la présence de code natif, puis vérifier l'alignement des segments ELF pour les bibliothèques partagées que vous trouvez. Android Studio fournit également des fonctionnalités qui vous aident à détecter automatiquement les problèmes d'alignement.

Si votre application n'utilise que du code écrit en langage de programmation Java ou Kotlin, y compris tous ses SDK et bibliothèques, elle est déjà compatible avec les appareils 16 bits. Toutefois, nous vous recommandons de tester votre application dans un environnement de 16 ko pour vérifier qu'il n'y a pas de régression inattendue dans le comportement de l'application.

Votre application utilise-t-elle du code natif ?

Votre application utilise du code natif si l'un des éléments suivants s'applique :

  • Votre application utilise du code C/C++ (natif). Si votre application utilise le NDK Android, cela signifie qu'elle utilise du code natif.
  • Votre application est associée à des bibliothèques ou dépendances natives tierces (comme des SDK) qui les utilisent.
  • Votre application est conçue par un outil de création d'applications tiers qui utilise des bibliothèques natives sur l'appareil.

Identifier les bibliothèques natives à l'aide de l'analyseur d'APK

L'analyseur d'APK est un outil qui vous permet d'évaluer divers aspects d'un APK créé. Pour vérifier si votre application utilise du code natif (qu'elle soit compatible ou non avec les pages de 16 ko) :

  1. Ouvrez Android Studio, puis cliquez sur File > Open (Fichier > Ouvrir) et choisissez un projet.
  2. Dans la barre de menu, cliquez sur Build > Analyze APK... (Compiler > Analyser l'APK...).

    Option du menu "Build" de Studio pour lancer l'analyseur d'APK
  3. Sélectionnez l'APK que vous souhaitez analyser.

  4. Regardez si le dossier lib contient des fichiers d'objets partagés (.so). Si des fichiers d'objets partagés sont présents, votre application utilise du code natif. La colonne Alignement affiche des messages d'avertissement pour tous les fichiers présentant des problèmes d'alignement. Si aucun fichier d'objet partagé n'est présent ou s'il n'y a pas de dossier lib, votre application n'utilise pas de code natif.

    Vue de l'analyseur d'APK montrant que des fichiers d'objets partagés sont présents

Détecter les problèmes d'alignement grâce aux vérifications automatisées

Android Studio vous avertit de manière proactive si vos bibliothèques ou APK prédéfinis ne sont pas compatibles avec une taille de page de 16 Ko. Utilisez l'analyseur d'APK pour identifier les bibliothèques à mettre à jour ou les modifications de code requises.

Notifications d'avertissement Studio concernant les problèmes d'alignement dans un projet

Lint dans Android Studio met également en évidence les bibliothèques natives qui ne sont pas alignées sur 16 Ko.

Avertissement du linter Studio concernant une bibliothèque native non alignée

Vérifier l'alignement des segments ELF pour les bibliothèques partagées

Pour toutes les bibliothèques partagées, vérifiez que leurs segments ELF sont correctement alignés à l'aide de l'alignement ELF de 16 ko. Si vous développez sur Linux ou macOS, vous pouvez utiliser le script check_elf_alignment.sh comme décrit dans la section suivante. Vous pouvez également utiliser directement les outils de ligne de commande.

Utiliser le script check_elf_alignment.sh (Linux ou macOS)

Suivez ces étapes pour vérifier l'alignement des segments ELF à l'aide du script check_elf_alignment.sh :

  1. Enregistrez le script check_elf_alignment.sh dans un fichier.

  2. Exécutez le script sur le fichier APK de votre application :

    check_elf_alignment.sh APK_NAME.apk
    

    Le script génère ALIGNED ou UNALIGNED pour toutes les bibliothèques partagées arm64-v8a.

  3. Si des bibliothèques partagées arm64-v8a ou x86_64 sont UNALIGNED, vous devrez mettre à jour l'empaquetage de ces bibliothèques, puis recompiler votre application et la tester à nouveau en suivant les étapes de cette section.

Utiliser directement les outils de ligne de commande

Pour vérifier l'alignement des segments ELF à l'aide d'outils de ligne de commande, procédez comme suit :

  1. Assurez-vous que les outils de compilation du SDK Android version 35.0.0 ou ultérieure et le NDK Android sont installés à l'aide du SDK Manager dans Android Studio ou de l'outil de ligne de commande sdkmanager.
  2. Extrayez le fichier APK de votre application :

    Linux ou macOS

    unzip APK_NAME.apk -d /tmp/my_apk_out
    

    Windows (PowerShell)

    Expand-Archive -Path .\APK_NAME.apk -DestinationPath ~\tmp\my_apk_out
    
  3. Dans le répertoire temporaire dans lequel vous avez extrait votre fichier APK, vérifiez le contenu du répertoire lib pour les fichiers d'objet partagé (.so). Il s'agit des mêmes fichiers d'objets partagés que ceux que vous avez vus lors de l'identification des bibliothèques natives à l'aide de l'analyseur d'APK. Exécutez la commande suivante sur chaque fichier d'objet partagé :

    Linux ou macOS

    SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump -p SHARED_OBJECT_FILE.so | grep LOAD
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-objdump.exe -p SHARED_OBJECT_FILE.so | Select-String -Pattern "LOAD"
    

    Où SDK_ROOT_LOCATION est le chemin d'accès au répertoire dans lequel vous avez installé le SDK Android, SHARED_OBJECT_FILE est le nom du fichier d'objet partagé que vous vérifiez et NDK_VERSION est la version du NDK Android que vous avez installée (par exemple, 28.0.12433566). Le résultat ressemblera à ce qui suit pour chaque fichier que vous vérifiez :

    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**14
    LOAD off    0x0000000000042a90 vaddr 0x0000000000043a90 paddr 0x0000000000043a90 align 2**14
    LOAD off    0x0000000000046230 vaddr 0x0000000000048230 paddr 0x0000000000048230 align 2**14
    
  4. Vérifiez les lignes de sortie pour vous assurer que les segments de charge n'ont pas de valeurs inférieures à 2**14. Si des segments de chargement ont des valeurs de 2**13, 2**12 ou inférieures, vous devez mettre à jour l'empaquetage de ces bibliothèques, puis recompiler votre application et la tester à nouveau en suivant les étapes de cette section.

  5. Ensuite, exécutez l'outil de ligne de commande zipalign sur le fichier APK de votre application :

    Linux ou macOS

    SDK_ROOT_LOCATION/Android/sdk/build-tools/35.0.0/zipalign -v -c -P 16 4 APK_NAME.apk
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\build-tools\35.0.0\zipalign.exe -v -c -P 16 4 APK_NAME.apk
    

    Où SDK_ROOT_LOCATION est le chemin d'accès au répertoire dans lequel vous avez installé le SDK Android, et APK_NAME est le nom du fichier APK de votre application. La dernière ligne du résultat indique "Verification successful" (Validation réussie) si toutes les bibliothèques partagées sont correctement alignées.

    Si la validation a échoué, certaines bibliothèques partagées doivent être réalignées. Vous devrez donc mettre à jour le packaging de ces bibliothèques, puis recompiler votre application et la tester à nouveau en suivant les étapes de cette section.

Vérifier l'indicateur de sécurité RELRO

Pour atténuer les failles de sécurité, les éditeurs de liens modernes utilisent l'indicateur Relocation Read-Only (RELRO) pour rendre les sections de relocalisation du fichier d'objet partagé en lecture seule après le chargement. Activez le flag RELRO dans votre compilation.

Une section RELRO dont l'adresse de début et la taille de segment (MemSize) ne sont pas alignées sur 16 ko fait planter l'application au moment de l'exécution avec une erreur de segmentation. Cela se produit si le fichier .so a été créé avec une chaîne d'outils NDK r27 ou antérieure sans activer les indicateurs concernés.

Exécutez la commande suivante sur chaque fichier d'objet partagé (Linux ou macOS) :

SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf -Wl SHARED_OBJECT_FILE.so | grep 'RELRO\|Type'

La chaîne GNU_RELRO s'affiche s'il existe un segment RELRO.

Ensuite, vérifiez l'alignement du segment RELRO en additionnant son adresse de décalage virtuel (VirtAddr) à la taille de la mémoire du segment (MemSiz), puis en divisant le résultat par 16 Ko (0x4000). Si le reste (modulo) est nul, le segment RELRO est aligné sur 16 Ko.

Voici un exemple de fichier .so non aligné :

Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align  
GNU_RELRO      0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x01510 R   0x1

Formule : (VirtAddr + MemSiz) % 0x4000 == 0

Résultat : (0xdfaf0 + 0x01510) % 0x4000 = 0xE1000 % 0x4000 == 0x1000

Comme 0x1000 n'est pas égal à zéro, ce fichier .so n'est pas conforme aux pages de 16 ko. La plage de protection RELRO de DC000 (saut de page précédent) à E4000 est en lecture seule, mais l'éditeur de liens Android s'attend à ce que la sous-plage de E1000 à E4000 soit accessible en écriture, ce qui entraîne une erreur de segmentation. Dans ce cas, recompilez le fichier .so comme décrit dans la section Compiler votre application à l'aide de l'alignement ELF de 16 Ko.

Voici un exemple de fichier .so aligné, avec un segment RELRO :

Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align
GNU_RELRO      0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x00510 R   0x1  

Voici un exemple de fichier .so sans segment RELRO :

Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align

Il s'agit d'un fichier .so trivialement compatible avec les pages de 16 ko, sans segment RELRO.

Voici un exemple de fichier .so aligné où GNU_RELRO se trouve dans son propre segment LOAD :

Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000680 0x000680 R E 0x4000
LOAD           0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x000980 RW  0x4000
GNU_RELRO      0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x000980 R   0x1

Formule : (VirtAddr + MemSiz) % 0x4000 == 0

Résultat : (0x4680 + 0x0980) % 0x4000 = 0x5000 % 0x4000 == 0x1000

Bien que 0x1000 ne soit pas égal à zéro, ce fichier .so est toujours conforme à la limite de 16 ko.

La formule modulo s'applique lorsque GNU_RELRO partage un segment LOAD avec des données accessibles en écriture ultérieures (telles que .data ou .bss).

Pour vérifier si GNU_RELRO se trouve dans son propre segment LOAD, inspectez les en-têtes du programme en exécutant llvm-readelf -Wl et en filtrant avec grep 'LOAD\|RELRO\|Type'. Comparez les valeurs VirtAddr et MemSiz de GNU_RELRO avec le segment LOAD contenant. Dans cet exemple, les deux ont VirtAddr 0x4680 et MemSiz 0x0980.

Comme l'intégralité du segment LOAD ne contient que des données RELRO, il n'y a pas de données accessibles en écriture dans la sous-plage allant de 0x5000 à 0x8000. De plus, tout segment LOAD inscriptible ultérieur commence sur une limite de page de 16 Ko distincte (à 0x8000 ou au-delà). La protection en lecture seule de l'éditeur de liens ne chevauche aucune donnée accessible en écriture, de sorte qu'aucune erreur de segmentation ne se produit.

Compiler votre application avec la prise en charge des appareils 16 ko

Si votre application utilise du code natif, suivez les étapes décrites dans les sections suivantes pour vous assurer qu'elle est compatible avec les appareils de 16 Ko :

  1. Mettre à jour l'empaquetage de vos bibliothèques partagées
  2. Compilez votre application en utilisant l'alignement ELF de 16 ko
  3. Corriger le code et résoudre les problèmes d'exécution
  4. Optimiser les allocateurs de mémoire personnalisés (le cas échéant)
  5. Vérifier la compatibilité des SDK avec les pages de 16 Ko

Mettre à jour le packaging de vos bibliothèques partagées

Passez à la version 8.5.1 ou ultérieure d'AGP et utilisez des bibliothèques partagées non compressées.

Utilisez bundletool pour vérifier l'alignement du fichier ZIP.

Pour voir l'alignement de votre bundle, utilisez :

bundletool dump config --bundle=<my .aab>  | grep alignment

Si vous voyez PAGE_ALIGNMENT_16K, cela signifie que votre bundle demande un alignement ZIP de 16 Ko. Si vous voyez PAGE_ALIGNMENT_4K, cela indique que l'APK créé à partir de cet AAB doit contenir des fichiers .so alignés sur 4 Ko dans le fichier ZIP.

AGP version 8.5.1 ou ultérieure

Les appareils de 16 Ko nécessitent que les applications fournies avec des bibliothèques partagées non compressées les alignent sur une limite d'alignement ZIP de 16 Ko. Pour ce faire, vous devez passer au plug-in Android Gradle (AGP) version 8.5.1 ou ultérieure. Pour en savoir plus sur le processus de mise à niveau, consultez la section Assistant de mise à niveau du plug-in Android Gradle.

AGP version 8.5 ou antérieure

Si vous ne pouvez pas passer à la version 8.5.1 ou ultérieure d'AGP, vous pouvez utiliser des bibliothèques partagées compressées. Mettez à jour votre configuration Gradle pour que Gradle compresse vos bibliothèques partagées lors de l'empaquetage de votre application. Vous éviterez ainsi les problèmes d'installation d'application liés aux bibliothèques partagées non alignées.

Groovy

Dans votre fichier build.gradle, ajoutez l'option suivante :

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging true
      }
  }
}

Kotlin

Dans votre fichier build.gradle.kts, ajoutez l'option suivante :

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging = true
      }
  }
}
AGP version 8.0 ou antérieure

Si vous utilisez une version d'AGP égale ou antérieure à la version 8.0, vous devez également désactiver l'option de bibliothèque native non compressée pour les app bundles dans votre fichier gradle.properties :

android.bundle.enableUncompressedNativeLibs=false

Compiler votre application à l'aide de l'alignement ELF de 16 Ko

Pour que votre application s'exécute sur les appareils 16 ko, les segments ELF des bibliothèques partagées doivent être correctement alignés à l'aide de l'alignement ELF 16 ko.

Si vous êtes développeur de jeux et que votre jeu s'exécute sur le moteur de jeu Unity, consultez le guide Unity. Si votre jeu s'exécute sur le moteur de jeu Unreal, consultez le guide Unreal.Pour les moteurs de jeu natifs, poursuivez avec ce guide.

Pour compiler votre application à l'aide de l'alignement ELF de 16 ko, suivez la procédure décrite dans l'une des sections suivantes, en fonction de la version du NDK Android que vous utilisez.

NDK Android r28 et versions ultérieures

Les versions r28 et ultérieures du NDK compilent par défaut les fichiers alignés sur 16 ko.

NDK Android r27 et versions antérieures

Pour permettre la compilation de bibliothèques partagées alignées sur 16 ko avec la version r27 ou antérieure du NDK Android, utilisez les options d'éditeur de liens suivantes :

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

Voici comment mettre à jour les fichiers de configuration de votre système de compilation :

ndk-build

Si vous utilisez ndk-build, mettez à jour votre Android.mk pour activer l'alignement ELF de 16 Ko :

LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384

CMake

Si vous utilisez CMake, mettez à jour votre CMakeLists.txt pour activer l'alignement ELF de 16 Ko :

target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
    "-Wl,-z,max-page-size=16384"
    "-Wl,-z,common-page-size=16384"
)

Corriger le code et résoudre les problèmes d'exécution

Même si votre application est alignée sur 16 ko, elle peut rencontrer des erreurs si des emplacements de votre code supposent qu'un appareil utilise une taille de page spécifique. Pour éviter cela, procédez comme suit :

  1. Supprimez toutes les dépendances codées en dur qui font référence à la constante PAGE_SIZE ou aux instances de votre logique de code qui supposent que la taille de page d'un appareil est de 4 Ko (4096).

    Utilisez plutôt getpagesize() ou sysconf(_SC_PAGESIZE).

  2. Recherchez les utilisations de mmap() et d'autres API qui nécessitent des arguments alignés sur la page, et remplacez-les par des alternatives si nécessaire.

Dans certains cas, si votre application utilise PAGE_SIZE comme valeur pratique qui n'est pas liée à la taille de page sous-jacente, cela n'entraînera pas de dysfonctionnement de votre application lorsqu'elle est utilisée en mode 16 ko. Toutefois, si cette valeur est transmise au noyau avec mmap sans MAP_FIXED, le noyau utilise toujours une page entière, ce qui gaspille de la mémoire. Pour ces raisons, PAGE_SIZE n'est pas défini lorsque le mode 16 Ko est activé sur NDK r27 et versions ultérieures.

Si votre application utilise PAGE_SIZE de cette manière et ne transmet jamais directement cette valeur au noyau, créez une variable avec un nouveau nom au lieu d'utiliser PAGE_SIZE. Cela indiquera qu'elle est utilisée à d'autres fins et ne reflète pas une véritable page de mémoire.

Optimiser les allocateurs de mémoire personnalisés

Sur les systèmes de 16 Ko, la plus petite unité de mémoire physique allouée par le système d'exploitation est quatre fois plus grande que sur les systèmes de 4 Ko. Si un allocateur personnalisé a été conçu sur la base d'hypothèses de 4 Ko, il peut disperser de petits objets sur plusieurs pages de 16 Ko et conserver de la mémoire vide inutilement. Cela peut augmenter considérablement l'utilisation de la mémoire physique (RSS) et dégrader l'efficacité de l'espace d'échange compressé (ZRAM).

Si votre code gère ses propres pools de mémoire, suivez ces recommandations :

1. Éviter les seuils d'octets codés en dur pour libérer de la mémoire

De nombreux allocateurs utilisent des limites d'octets fixes pour décider quand libérer de la mémoire vers l'OS à l'aide de madvise(MADV_DONTNEED) (par exemple, ne libérer de la mémoire que si les objets actifs occupent moins de 8 Ko).

Sur un système de 16 Ko, même un seul objet actif de 16 octets épingle une page entière de 16 Ko (ce qui est supérieur à 8 Ko). Par conséquent, le seuil de libération n'est jamais atteint et l'allocateur ne renvoie jamais au noyau la mémoire inutilisée environnante.

À faire : n'utilisez jamais de constantes d'octets codées en dur pour les heuristiques de libération de page. Faites évoluer les seuils de publication de manière dynamique au moment de l'exécution en fonction de la taille réelle de la page à l'aide de sysconf(_SC_PAGESIZE).

2. Remplir d'abord les pages déjà utilisées (allocation dense-first)

Si un allocateur distribue la mémoire dans l'ordre FIFO (premier entré, premier sorti) ou par tourniquet, les nouvelles allocations sont réparties sur plusieurs pages de 16 Ko partiellement remplies. Un seul objet sur une page conserve l'intégralité des 16 Ko résidents dans la RAM physique.

À faire : Allouez toujours de nouveaux objets à partir de la page ou de la tranche la plus pleine (la plus dense) avant de toucher aux pages vides ou peu utilisées. En concentrant les nouvelles allocations sur les pages déjà sales, les pages peu utilisées peuvent naturellement atteindre zéro objet actif, de sorte que la page entière de 16 Ko peut être libérée pour l'OS.

3. Aligner les pools de mémoire sur 16 ko et maintenir des tailles de pool modérées

Les plages multipages conçues pour les systèmes de 4 ko peuvent contenir un espace mémoire non libéré excessif sur les kernels de 16 ko. De plus, les classes de taille qui ne se divisent pas de manière égale en 16 Ko entraînent une fragmentation à la fin de chaque page.

Ce que vous devez faire :

  • Assurez-vous que tous les pools de mémoire, les limites de slab et les alignements de tampon sont des multiples exacts de la taille de la page d'exécution.
  • Réévaluez les tailles d'étendue multipage pour les classes d'objets de petite taille afin d'éviter d'allouer des slabs trop grands qui piègent la mémoire inactive.

4. Libérer immédiatement la mémoire physique pour les grands tampons mis en cache

Les allocateurs personnalisés mettent souvent en cache de grands tampons (> 64 Ko) dans un pool en mémoire afin qu'ils puissent être réutilisés sans payer les frais généraux des appels système mmap ou munmap. Toutefois, conserver ces tampons sales en mémoire gaspille des mégaoctets de RAM physique en attendant un minuteur d'éviction.

Que faire : conservez la plage d'adresses de mémoire virtuelle réservée pour une réutilisation rapide, mais appelez immédiatement madvise(..., MADV_DONTNEED) ou madvise(..., MADV_FREE) lorsque vous renvoyez un tampon au cache. Le système d'exploitation récupère immédiatement la RAM physique, tandis que votre application peut toujours réutiliser l'adresse virtuelle instantanément sans réallocation.

5. Mise à zéro de la mémoire lors de la libération au lieu de l'allocation pour la compression ZRAM

Android utilise l'espace d'échange compressé (ZRAM) pour conserver les applications en arrière-plan en mémoire. Sur les appareils de 16 Ko, si une page contient ne serait-ce qu'un seul objet actif, l'intégralité de la page de 16 Ko reste résidente ou est transférée vers la ZRAM. Les données inutiles restantes (telles que les pointeurs et les chaînes obsolètes) sur les parties précédemment libérées de cette page se compressent mal.

Si votre allocateur met la mémoire à zéro (par exemple, pour des allocations de sécurité ou initialisées à zéro), envisagez de mettre à zéro lors de la désallocation (free()) plutôt que lors de l'allocation :

  • Les pages épinglées coûtent moins cher : la mémoire inactive sur les pages de 16 ko partiellement remplies est compressée à presque rien dans la ZRAM. Les pages épinglées ne gaspillent donc pas d'espace d'échange physique.
  • Frais généraux de cache minimaux : au moment où free() est appelé, la mémoire est déjà chaude dans le cache du processeur, ce qui évite d'autres défauts de cache par la suite.

Résumé des recommandations

Région Recommandation Impact attendu
Seuils de suppression Mettez à l'échelle les seuils de publication de manière dynamique à l'aide de sysconf(_SC_PAGESIZE). Empêche la logique de publication de se bloquer définitivement.
Ordre d'allocation Allouer d'abord à partir de la page ou de la tranche la plus dense (presque pleine). Réduit la mémoire résidente (RSS) en regroupant les objets actifs.
Taille de la portée Alignez les classes de taille sur des multiples de 16 Ko et évitez les slabs surdimensionnés. Élimine la fragmentation des pages de fin et réduit l'espace mémoire inutilisé.
Caches de tampon Appelez madvise(MADV_DONTNEED) immédiatement lors de la mise en cache de grands tampons. Élimine le gonflement de la RAM inactive tout en conservant une réutilisation virtuelle rapide.
Swap / ZRAM Mise à zéro de la mémoire sur free() au lieu de l'allocation. Améliore les taux de compression ZRAM pour que les pages épinglées coûtent moins cher.

Vérifier la compatibilité des SDK avec les pages de 16 ko

De nombreux SDK sont compatibles avec les tailles de page de 16 Ko, en particulier si vous les créez vous-même ou si vous obtenez des précompilés récents. Toutefois, comme certains SDK précompilés ou certaines versions de SDK ne sont pas compatibles avec 16 Ko, vous devez consulter le site Web de chaque fournisseur de SDK pour déterminer la version à utiliser avec 16 Ko.

Tester votre appli dans un environnement 16 ko

Après avoir compilé votre application pour qu'elle soit compatible avec les appareils 16 Ko, vous devez la tester dans un environnement 16 Ko pour voir si elle subit des régressions. Pour ce faire, procédez comme suit :

  1. Configurez le SDK Android 15 ou version ultérieure.

  2. Configurez l'un des environnements de test suivants :

  3. Démarrez votre appareil de test, puis exécutez la commande suivante pour vérifier qu'il utilise un environnement de 16 ko :

    adb shell getconf PAGE_SIZE
    

    La commande doit renvoyer la valeur 16384.

  4. Exécutez la commande zipalign suivante pour vérifier que votre application est alignée sur 16 Ko, où APK_NAME est le nom du fichier APK de votre application :

    zipalign -c -P 16 -v 4 APK_NAME.apk
    
  5. Testez minutieusement votre application, en vous concentrant sur les zones qui pourraient être affectées par la modification des instances de code faisant référence à des tailles de page spécifiques.

Configurer Android Emulator avec une image système basée sur 16 Ko

Pour configurer un environnement de 16 Ko à l'aide d'Android Emulator, procédez comme suit :

  1. Dans Android Studio, cliquez sur Tools > SDK Manager (Outils > Gestionnaire de SDK).
  2. Dans l'onglet SDK Platforms (Plates-formes SDK), sélectionnez Show Package Details (Afficher les détails du package), puis développez la section Android VanillaIceCream (Android VanillaIceCream) ou version ultérieure et sélectionnez une ou les deux images système de l'émulateur suivantes, en fonction des appareils virtuels que vous souhaitez créer :

    • Image système expérimentale Google APIs ARM 64 v8a avec taille de page de 16 Ko
    • Image système Google APIs Experimental 16 KB Page Size Intel x86_64 Atom
    Télécharger des images système d'émulateur de 16 Ko à l'aide de SDK Manager dans Android Studio
  3. Cliquez sur Appliquer > OK pour télécharger les images système que vous avez sélectionnées.

  4. Suivez les étapes pour configurer un appareil virtuel pour Android 15. Lorsque vous êtes invité à sélectionner une image système, sélectionnez l'image système de 16 ko que vous avez téléchargée. Si elle n'est pas recommandée automatiquement, vous pouvez trouver l'image système de 16 Ko dans l'onglet Autres images.

    Recherchez l'image de l'émulateur 16 ko dans l'onglet &quot;Autres images&quot;.

Lancer l'émulateur

Une fois que vous avez terminé de configurer l'Android Emulator et les appareils virtuels, lancez l'émulateur à partir du menu de l'appareil cible ou à partir de la ligne de commande.

Activer le mode 16 ko sur un appareil à l'aide des options pour les développeurs

Activez l'option pour les développeurs Démarrer avec une page de 16 ko pour démarrer un appareil en mode 16 ko.

Dans les versions QPR d'Android 15, vous pouvez utiliser l'option pour les développeurs disponible sur certains appareils pour démarrer l'appareil en mode 16 Ko et effectuer des tests sur l'appareil. Avant d'utiliser l'option pour les développeurs, accédez à Paramètres > Système > Mises à jour logicielles et appliquez les mises à jour disponibles.

Cette option pour les développeurs est disponible sur les appareils suivants :

  • Pixel 8 et 8 Pro (avec Android 15 QPR1 ou version ultérieure)

  • Pixel 8a (avec Android 15 QPR1 ou version ultérieure)

  • Pixel 9, 9 Pro et 9 Pro XL (avec Android 15 QPR2 ou version ultérieure)

  • Pixel 9a (avec Android 16 ou version ultérieure)

Mode de rétrocompatibilité 16 ko

Avertissement en mode de compatibilité de taille de page

Avertissement en mode de compatibilité de taille de page

L'option de rétrocompatibilité 16 ko est disponible lorsqu'un appareil exécute un kernel 16 ko. Le gestionnaire de packages exécute une application en mode de rétrocompatibilité 16 Ko lorsque les conditions suivantes sont remplies :

  • Si l'application comporte des fichiers ELF (avec une extension .so) avec un alignement de segment LOAD de 4 Ko.
  • Si l'APK compressé contient des fichiers ELF non compressés alignés sur un fichier ZIP de 4 Ko.

Si le gestionnaire de packages a activé le mode de rétrocompatibilité 16 ko pour une application, celle-ci affiche un avertissement lors de son premier lancement, indiquant qu'elle s'exécute en mode de rétrocompatibilité 16 ko.

Le mode de rétrocompatibilité 16 Ko permet à certaines applications de fonctionner, mais pour une fiabilité et une stabilité optimales, les applications doivent toujours être alignées sur 16 Ko.

Sur la page d'informations de l'application, sous Avancé, activez ou désactivez le paramètre Exécuter l'application en mode de compatibilité de taille de page pour activer ou désactiver le mode de rétrocompatibilité 16 Ko pour une application spécifique. Ce paramètre n'est visible que lorsque l'appareil s'exécute avec une taille de page de 16 Ko.

Paramètre du mode de compatibilité de taille de page

Paramètre du mode de compatibilité de taille de page

Pour forcer la rétrocompatibilité 16 ko pour toutes les applications de l'appareil :

adb shell setprop bionic.linker.16kb.app_compat.enabled true
adb shell setprop pm.16kb.app_compat.disabled false

Pour forcer la désactivation de la rétrocompatibilité 16 ko pour toutes les applications de l'appareil :

adb shell setprop bionic.linker.16kb.app_compat.enabled false
adb shell setprop pm.16kb.app_compat.disabled true

Dans Android 17, vous pouvez également forcer la désactivation de la rétrocompatibilité 16 Ko pour chaque application et provoquer l'arrêt immédiat de tout binaire incompatible :

    adb shell setprop bionic.linker.16kb.app_compat.enabled fatal
    adb shell setprop pm.16kb.app_compat.disabled true

Définissez la propriété android:pageSizeCompat sur "enabled" ou "disabled" pour activer ou désactiver le mode de rétrocompatibilité pour une application spécifique dans son fichier AndroidManifest.xml. Lorsque cette propriété est définie, l'application n'affiche pas d'avertissements de mode de rétrocompatibilité au lancement.