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

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

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

Установите Android на 16 КБ

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

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

Для платформы 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

Проверка двоичных файлов и готовых сборок на соответствие 16 КБ ELF.

Лучший способ проверить выравнивание и поведение во время выполнения — протестировать и запустить скомпилированное ядро размером 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 и более поздними версиями.