Tamaño de página de 16 KB

El tamaño de la página es el nivel de detalle con el que un SO administra la memoria. La mayoría de las CPU actuales admiten un tamaño de página de 4 KB, por lo que el SO y las apps de Android se compilaron y optimizaron históricamente para ejecutarse con un tamaño de página de 4 KB. Las CPUs de ARM admiten el tamaño de página más grande de 16 KB y, a partir de Android 15, el 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 de desarrollador o como opción para desarrolladores para que los OEM y los desarrolladores de apps se preparen para cambiar al modo de 16 KB en todas partes en el futuro.

Android 15 y versiones posteriores son compatibles con 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.

Cómo establecer el espacio de usuario de Android en 16 KB

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

Para los destinos arm64, si usas Kleaf para compilar tu kernel, --page_size=16k compila el kernel en el 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 habilitar la compatibilidad con el tamaño de página de 16 KB en el espacio de usuario de Android, establece las siguientes opciones de compilación en tu producto:

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true quita la definición de 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, que garantiza que los archivos ELF de la plataforma se compilen con una alineación de 16 KB. Este tamaño mayor que el 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 destino 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 se aprueba, 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 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 la asignación de memoria del kernel, y debes tener esto en cuenta para escribir código que no solo sea compatible, sino que también tenga el máximo rendimiento y sea mínimamente intensivo en 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 implementar esto. En otras palabras, cuando se solicita memoria al 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 de cola" 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, se asignarán 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 asignaría 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 de la misma memoria.

Cuando uses mmap, asegúrate de redondear el tamaño que solicitas hasta el tamaño de página más cercano. Esto garantiza que toda la cantidad de memoria que asigna el kernel sea directamente visible para el espacio de usuario en los valores del tiempo de ejecución, en lugar de solicitarse de forma implícita y poder acceder a ella 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 del vinculador:

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

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

La mejor manera de verificar la alineación y el comportamiento del entorno 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 (experimental de AOSP), puedes configurar PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true en 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 objetos 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 inician con Android 15 y versiones posteriores.