Размер страницы 16 КБ

Размер страницы – это гранулярность, с которой ОС управляет памятью. Большинство современных процессоров поддерживают страницы размером 4 КБ, поэтому ОС Android и приложения для нее традиционно создавались и оптимизировались для работы с таким размером страниц. Процессоры ARM поддерживают страницы размером 16 КБ, а начиная с Android 15, AOSP также поддерживает сборку Android со страницами размером 16 КБ. Этот вариант использует дополнительную память, но повышает производительность системы. В Android 15 этот параметр не включен по умолчанию, но доступен в режиме разработчика или как параметр для разработчиков приложений и производителей устройств. Это позволяет подготовиться к переходу на режим 16 КБ в будущем.

В Android 15 и более поздних версиях поддерживается сборка Android с выравниванием ELF размером 16 КБ, которое работает с ядрами размером 4 КБ и 16 КБ, начиная с версии android14-6.1. При использовании с ядром 16 КБ эта конфигурация задействует дополнительную память, но повышает производительность системы.

Как задать размер страницы памяти 16 КБ в Android

Страницы размером 16 КБ поддерживаются только на целевых устройствах arm64 с ядрами 16 КБ. Однако вы также можете симулировать пространство пользователя 16 КБ на x86_64 для Cuttlefish.

Пространство ядра

Если вы используете Kleaf для сборки ядра, --page_size=16k собирает ядро в режиме 16 КБ.arm64 Если вы напрямую используете конфигурацию ядра Linux, то можете выбрать страницы размером 16 КБ, задав значение CONFIG_ARM64_16K_PAGES вместо CONFIG_ARM64_4K_PAGES.

Информацию о готовых двоичных файлах GKI с размером страницы 16 КБ, поддерживаемых ветвях, выпусках и повторных сборках можно найти в статьях Выпуски GKI с размером страницы 16 КБ и Конечные сборки GKI.

Пользовательское пространство

Чтобы включить поддержку страниц размером 16 КБ в пользовательском пространстве Android, задайте следующие параметры сборки:

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true удаляет PAGE_SIZE define и заставляет компоненты определять размер страницы во время выполнения.
  • PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384, которая обеспечивает выравнивание файлов ELF платформы по границе 16 КБ. Такой размер выбран для обеспечения совместимости с будущими версиями. При выравнивании ELF по 16 КБ ядро может поддерживать страницы размером 4 КБ и 16 КБ.

Проверьте флаги сборки

Выбрав целевую платформу lunch, убедитесь, что флаги сборки настроены правильно:

$ 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

Если предыдущие две команды вернули значения 16384 и true соответственно, флаги сборки настроены правильно для работы с ядром размером 16 КБ. Однако даже если сборка прошла успешно, во время выполнения могут возникнуть проблемы из-за различий в среде размером 16 КБ.

Программирование системы с размером страницы 16 КБ

Подавляющее большинство кода на любом устройстве Android не имеет прямого отношения к размеру страницы. Однако для кода, который работает со страницами, поведение ядра при выделении памяти меняется. Это нужно учитывать, чтобы писать код, который будет не только совместимым, но и максимально производительным и минимально ресурсоемким.

Если вы вызовете mmap для области размером 1, 2 или 4 КБ в системе с размером страницы 4 КБ, система зарезервирует 4 КБ. Другими словами, при запросе памяти у ядра оно всегда должно округлять запрошенную память до ближайшего размера страницы. Например, если вы выделите область размером 5 КБ в области размером 4 КБ, ядро выделит 8 КБ.

В ядре с размером страницы 16 КБ эти "хвосты" больше. Например, при использовании ядра с размером страницы 16 КБ все эти выделения памяти (от 1 до 5 КБ) будут занимать 16 КБ. Если вы запросите 17 КБ, будет выделено 32 КБ.

Например, в системе с размером страницы 4 КБ можно выделить две анонимные области чтения-записи по 4 КБ. Однако в ядре с размером страницы 16 КБ для этого потребуется выделить две страницы, то есть 32 КБ. Если используется ядро размером 16 КБ, эти регионы можно объединить в одну страницу для чтения или записи, чтобы использовать только 16 КБ. В этом случае будет потрачено впустую 8 КБ по сравнению с ядром размером 4 КБ. Чтобы ещё больше сократить использование памяти, можно объединить больше страниц. На самом деле в максимально оптимизированной системе со страницами размером 16 КБ требуется меньше памяти, чем в системе со страницами размером 4 КБ, поскольку таблица страниц в четыре раза меньше для того же объема памяти.

При использовании mmap округляйте запрашиваемый размер до ближайшего размера страницы. Это гарантирует, что весь объем памяти, выделенный ядром, будет напрямую виден в пользовательском пространстве в виде значений времени выполнения, а не будет запрашиваться неявно и становиться доступным случайно или неявно.

Как создавать общие библиотеки с выравниванием ELF 16 КБ

Чтобы создать общие библиотеки, которые являются частью проекта Android, достаточно настроек, описанных в разделе Как включить размер страницы 16 КБ.

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
  • PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384

Чтобы создать общие библиотеки, которые не входят в проект для Android, вам нужно передать этот флаг компоновщика:

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

Проверьте двоичные файлы и предварительно созданные объекты на соответствие требованиям к выравниванию ELF для страниц размером 16 КБ

Лучший способ проверить выравнивание и поведение во время выполнения – протестировать и запустить приложение на скомпилированном ядре с размером страницы 16 КБ. Однако, чтобы выявлять некоторые проблемы раньше:

  • Начиная с Android 16, вы можете задать PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true во время сборки. Используйте ignore_max_page_size: true в Android.bp и LOCAL_IGNORE_MAX_PAGE_SIZE := true в Android.mk, чтобы временно игнорировать их. Эти настройки проверяют все предварительно созданные сборки и позволяют обнаружить, когда одна из них обновлена, но не выровнена по 16 КБ.

  • Вы можете запустить atest elf_alignment_test, чтобы проверить выравнивание ELF-файлов на устройствах с Android 15 и более поздними версиями.