Tamaño de página de 16 KB

El tamaño de página es la granularidad con la que un SO administra la memoria. La mayoría de las CPUs actuales admiten un tamaño de página de 4 KB, por lo que el SO Android y las apps se compilaron y optimizaron históricamente para ejecutarse con un tamaño de página de 4 KB. Las CPUs ARM admiten el tamaño de página más grande de 16 KB y, a partir de Android 15, AOSP también admite la compilación de Android con un tamaño de página de 16 KB. Esta opción usa memoria adicional, pero mejora el rendimiento del sistema. A partir de Android 15, esta opción no está habilitada de forma predeterminada, pero está disponible como modo para desarrolladores o como opción para desarrolladores para que los OEMs y los desarrolladores de apps se preparen para cambiar al modo de 16 KB en el futuro.

Android 15 y versiones posteriores admiten la compilación de Android con una alineación ELF de 16 KB, que funciona con kernels de 4 KB y 16 KB a partir de android14-6.1. Cuando se usa con un kernel de 16 KB, esta configuración usa memoria adicional, pero mejora el rendimiento del sistema.

Configura Android en 16 KB

Las páginas de 16 KB solo se admiten en objetivos arm64 con kernels de 16 KB. Sin embargo, también existe la opción de simular el espacio de usuario de 16 KB en x86_64 para Cuttlefish.

Espacio del kernel

Para los objetivos arm64, si usas Kleaf para compilar tu kernel, --page_size=16k compila el kernel en modo de 16 KB. Si usas directamente la configuración del kernel de Linux, puedes seleccionar páginas de 16 KB configurando CONFIG_ARM64_16K_PAGES en lugar de CONFIG_ARM64_4K_PAGES.

Para obtener información sobre los archivos binarios de la imagen genérica de kernel (GKI) de 16 KB precompilados, las ramas compatibles y los detalles de la versión y el respin, consulta Versiones de GKI de 16 KB y compilaciones de lanzamiento de GKI.

Espacio de usuario

Para habilitar la compatibilidad con el tamaño de página de 16 KB en el espacio de usuario de Android, configura las siguientes opciones de compilación en tu producto:

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true quita la definición PAGE_SIZE y hace que los componentes determinen el tamaño de la página durante el tiempo de ejecución.
  • PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384, lo que garantiza que los archivos ELF de la plataforma se compilen con una alineación de 16 KB. Este tamaño más grande de lo necesario es para la compatibilidad futura. Con la alineación ELF de 16 KB, el kernel puede admitir tamaños de página de 4 KB/16 KB.

Verifica las marcas de compilación

Después de seleccionar el objetivo lunch, verifica que las marcas de compilación estén configuradas correctamente en el entorno:

$ 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

Si los dos comandos anteriores muestran 16384 y true, respectivamente, las marcas de compilación están configuradas correctamente para funcionar con un kernel de 16 KB. Sin embargo, incluso si una compilación pasa, es posible que aún haya problemas de tiempo de ejecución debido a las diferencias en un entorno de 16 KB.

Programación del sistema de tamaño de página de 16 KB

La gran mayoría del código en cualquier dispositivo con tecnología Android no se ocupa directamente del tamaño de la página. Sin embargo, para el código que se ocupa de las páginas, cambia el comportamiento de asignación de memoria del kernel, y debes tenerlo en cuenta para escribir código que no solo sea compatible, sino también que tenga el máximo rendimiento y el mínimo uso de recursos.

Si llamas a mmap en una región de 1 KB, 2 KB o hasta 4 KB en un sistema de 4 KB, el sistema reserva 4 KB para implementarlo. En otras palabras, cuando se solicita memoria del kernel, este siempre debe redondear la memoria solicitada al tamaño de página más cercano. Por ejemplo, si asignas una región de 5 KB en una región de 4 KB, el kernel asigna 8 KB.

En un kernel de 16 KB, estos "extremos" adicionales de las páginas son más grandes. Por ejemplo, todas estas asignaciones, de 1 KB a 5 KB, asignarían 16 KB cuando se usan con un kernel de 16 KB. Si solicitas 17 KB, asigna 32 KB.

Por ejemplo, en un sistema de 4 KB, está bien asignar dos regiones anónimas de lectura y escritura de 4 KB. Sin embargo, en un kernel de 16 KB, esto daría como resultado la asignación de dos páginas o 32 KB. En un kernel de 16 KB, si es posible, estas regiones se pueden combinar en una sola página de lectura o escritura para que solo se usen 16 KB, lo que desperdicia 8 KB en comparación con el caso del kernel de 4 KB. Para reducir aún más el uso de memoria, se pueden combinar más páginas. De hecho, en un sistema de 16 KB que está optimizado al máximo, las páginas de 16 KB requieren menos memoria que los sistemas de 4 KB porque la tabla de páginas es un cuarto del tamaño para la misma memoria.

Cuando uses mmap, asegúrate de redondear el tamaño que solicitas al tamaño de página más cercano. Esto garantiza que la cantidad total de memoria que asigna el kernel sea directamente visible para el espacio de usuario en los valores de tiempo de ejecución, en lugar de solicitarse de forma implícita y ser accesible de forma implícita o accidental.

Compila bibliotecas compartidas con alineación ELF de 16 KB

Para compilar bibliotecas compartidas que forman parte del proyecto de Android, la configuración anterior en Habilitar tamaño de página de 16 KB es suficiente:

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
  • PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384

Para compilar bibliotecas compartidas que no forman parte del proyecto de Android, debes pasar esta marca de vinculador:

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

Verifica los archivos binarios y los precompilados para la alineación ELF de 16 KB

La mejor manera de verificar la alineación y el comportamiento del tiempo de ejecución es probar y ejecutar en un kernel compilado de 16 KB. Sin embargo, para detectar algunos problemas antes, haz lo siguiente:

  • A partir de Android 16, puedes configurar PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true durante el tiempo de compilación. Usa ignore_max_page_size: true en Android.bp y LOCAL_IGNORE_MAX_PAGE_SIZE := true en Android.mk para ignorarlos temporalmente. Esta configuración verifica todos los precompilados y te permite detectar cuándo se actualiza uno , pero no está alineado con 16 KB.

  • Puedes ejecutar atest elf_alignment_test, que verifica la alineación de los archivos ELF integrados en el dispositivo en dispositivos que se lanzan con Android 15 y versiones posteriores.