Размер страницы — это степень детализации, с которой ОС управляет памятью. Большинство процессоров сегодня поддерживают размер страницы 4 КБ, поэтому ОС Android и приложения исторически создавались и оптимизировались для работы с размером страницы 4 КБ. Процессоры ARM поддерживают больший размер страницы 16 КБ, а начиная с Android 15 AOSP также поддерживает создание Android с размером страницы 16 КБ. Этот вариант использует дополнительную память, но повышает производительность системы. Начиная с Android 15, эта опция не включена по умолчанию, но она доступна в качестве режима разработчика или опции разработчика для OEM-производителей и разработчиков приложений, чтобы подготовиться к переключению на режим 16 КБ повсюду в будущем.
Android 15 и более поздних версий поддерживают сборку Android с выравниванием ELF размером 16 КБ, которое работает с ядрами размером 4 КБ и 16 КБ. При использовании ядра размером 16 КБ эта конфигурация использует дополнительную память, но повышает производительность системы.
Установите пользовательское пространство Android на 16 КБ.
Страницы размером 16 КБ поддерживаются только на целевых устройствах arm64
с ядрами 16 КБ. Однако существует также возможность имитировать пользовательское пространство размером 16 КБ на x86_64
для Cuttlefish.
Для целей arm64
, если вы используете Kleaf для сборки ядра, --page_size=16k
собирает ядро в режиме 16 КБ. Если вы напрямую используете конфигурацию ядра Linux, вы можете выбрать страницы размером 16 КБ, установив CONFIG_ARM64_16K_PAGES
вместо CONFIG_ARM64_4K_PAGES
.
Чтобы включить поддержку размера страницы 16 КБ в пользовательском пространстве Android, установите в своем продукте следующие параметры сборки:
-
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
удаляет определениеPAGE_SIZE
и заставляет компоненты определять размер страницы во время выполнения. -
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 КБ эти дополнительные «хвосты» страниц больше. Например, все эти выделения, от 1 КБ до 5 КБ, будут выделять 16 КБ при использовании с ядром размером 16 КБ. Если вы запрашиваете 17 КБ, выделяется 32 КБ.
Например, в системе размером 4 КБ можно выделить две анонимные области для чтения и записи по 4 КБ. Однако в ядре размером 16 КБ это приведет к выделению двух страниц или 32 КБ. В ядре размером 16 КБ, если возможно, эти области можно объединить в одну страницу, доступную для чтения или записи, чтобы использовалось только 16 КБ, тратя 8 КБ впустую по сравнению со случаем ядра 4 КБ. Чтобы еще больше сократить использование памяти, можно объединить больше страниц. Фактически, в максимально оптимизированной системе 16 КБ страницы размером 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 W (экспериментальная версия AOSP), вы можете установить
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 и более поздних версий.