Rozmiar strony to poziom szczegółowości, na którym system operacyjny zarządza pamięcią. Większość współczesnych procesorów obsługuje strony o rozmiarze 4 KB, dlatego system operacyjny Android i aplikacje zostały zbudowane i zoptymalizowane pod kątem działania z takimi stronami. Procesory ARM obsługują większy rozmiar strony 16 KB, a od Androida 15 AOSP obsługuje kompilowanie Androida z użyciem strony 16 KB. Ta opcja zużywa więcej pamięci, ale poprawia wydajność systemu. W Androidzie 15 ta opcja nie jest domyślnie włączona, ale jest dostępna jako tryb programisty lub opcja dla OEM-ów i deweloperów aplikacji, aby mogli przygotować się do przejścia na tryb 16 KB.
Android 15 i nowsze wersje obsługują kompilowanie Androida z wyrównaniem ELF 16 KB, które działa z jądrami 4 KB i 16 KB od wersji android14-6.1
.
W przypadku jądra o rozmiarze 16 KB ta konfiguracja zużywa więcej pamięci, ale poprawia wydajność systemu.
Ustaw przestrzeń użytkownika Androida na 16 KB
Strony 16 KB są obsługiwane tylko na urządzeniach arm64
z jądrem 16 KB.
W przypadku Cuttlefisha dostępna jest też opcja symulowania 16 KB przestrzeni użytkownika na x86_64
.
Jeśli do kompilowania jądra używasz Kleaf, a docelami są urządzenia arm64
, --page_size=16k
kompiluje jądro w trybie 16 KB.
Jeśli używasz bezpośrednio konfiguracji jądra Linuksa, możesz wybrać strony o długości 16 KB, ustawiając CONFIG_ARM64_16K_PAGES
zamiast CONFIG_ARM64_4K_PAGES
.
Aby włączyć obsługę stron o rozmiarze 16 KB w przestrzeni użytkownika Androida, ustaw w produkcie te opcje kompilacji:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
usuwa definicjęPAGE_SIZE
i powoduje, że komponenty określają rozmiar strony w czasie wykonywania.PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
, co zapewnia, że pliki ELF platformy są kompilowane z wyrównaniem 16 KB. Większy rozmiar niż wymagany jest potrzebny ze względu na zgodność w przyszłości. Dzięki wyrównaniu ELF 16 KB jądro może obsługiwać strony o rozmiarze 4 KB lub 16 KB.
Sprawdzanie flag kompilacji
Po wybraniu celu lunch
sprawdź, czy flagi kompilacji są prawidłowo skonfigurowane w środowisku:
$ 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
Jeśli poprzednie 2 polecenia zwrócą odpowiednio wartości 16384
i true
, flagi kompilacji są prawidłowo skonfigurowane do pracy z jądrem o rozmiarze 16 KB. Jednak nawet jeśli kompilacja przejdzie, mogą wystąpić problemy z działaniem ze względu na różnice w środowisku 16 KB.
Programowanie systemu z rozmiarem strony 16 KB
Większość kodu na dowolnym urządzeniu z Androidem nie ma bezpośredniego wpływu na rozmiar strony. W przypadku kodu, który ma do czynienia ze stronami, zachowanie przydziału pamięci przez jądro ulega zmianie. Musisz to mieć na uwadze, aby napisać kod, który jest nie tylko zgodny, ale też zapewnia maksymalną wydajność i minimalne zużycie zasobów.
Jeśli wywołasz funkcję mmap
w regionie o rozmiarze 1 KB, 2 KB lub maksymalnie 4 KB na systemie 4 KB, system zarezerwuje 4 KB na potrzeby jego implementacji. Innymi słowy, gdy żądanie pamięci jest wysyłane do jądra, jądro musi zawsze zaokrąglać żądaną pamięć do najbliższego rozmiaru strony. Jeśli np. przydzielisz region o rozmiarze 5 KB na region o rozmiarze 4 KB, jądro przydzieli 8 KB.
W przypadku jądra 16 KB te dodatkowe „ogonki” stron są dłuższe. Na przykład wszystkie te alokacje, od 1 KB do 5 KB, przy użyciu rdzenia 16 KB będą alokować 16 KB. Jeśli żądasz 17 KB, przydziela 32 KB.
Na przykład w systemie 4 KB można przydzielić 2 anonimowe regiony o rozmiarze 4 KB z możliwością odczytu i zapisu. Jednak w przypadku jądra 16 KB oznaczałoby to przydzielenie 2 stron, czyli 32 KB. W przypadku jądra 16 KB te regiony można połączyć w jedną stronę do odczytu lub zapisu, aby wykorzystać tylko 16 KB, co oznacza marnowanie 8 KB w porównaniu do przypadku jądra 4 KB. Aby jeszcze bardziej zmniejszyć wykorzystanie pamięci, można połączyć więcej stron. W systemie 16 KB z maksymalnie zoptymalizowanymi stronami 16 KB zajmują one mniej pamięci niż strony 4 KB, ponieważ tabela stron zajmuje 1/4 pamięci.
Gdy używasz mmap
, upewnij się, że zażądany rozmiar jest zaokrąglony do najbliższego rozmiaru strony. Dzięki temu cała ilość pamięci przydzielanej przez jądro jest bezpośrednio widoczna w przestrzeni użytkownika w wartościach czasu wykonywania, zamiast być niejawnie żądana i dostępna w sposób domyślny lub przypadkowy.
Tworzenie bibliotek udostępnionych z wyrównaniem ELF 16 KB
Aby kompilować biblioteki współdzielone, które są częścią projektu Androida, wystarczą wcześniejsze ustawienia w sekcji Włączanie rozmiaru strony 16 KB:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
Aby kompilować biblioteki współdzielone, które nie są częścią projektu Androida, musisz podać ten parametr linkera:
-Wl,-z,max-page-size=16384
Sprawdzanie binarnych plików binarnych i uprzednio skompilowanych pod kątem zgodności z elfem 16 KB
Najlepszym sposobem weryfikacji wyrównania i zachowania w czasie wykonywania jest przetestowanie i uruchomienie na skompilowanym rdzeniu o rozmiarze 16 KB. Aby jednak wcześniej wykrywać niektóre problemy:
Od wersji 16 Androida (wersja eksperymentalna AOSP) możesz ustawiać wartość
PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true
w czasie kompilacji. Aby tymczasowo zignorować te wartości, użyj wartościignore_max_page_size: true
w elemencieAndroid.bp
i wartościLOCAL_IGNORE_MAX_PAGE_SIZE := true
w elemencieAndroid.mk
. Te ustawienia weryfikują wszystkie wstępnie utworzone pliki i pozwalają wykryć, kiedy jeden z nich został zaktualizowany, ale nie jest zgodny z formatem 16 KB.Możesz uruchomić
atest elf_alignment_test
, który weryfikuje wyrównanie plików ELF na urządzeniach z Androidem w wersji 15 lub nowszej.