Android 17 i nowsze wersje obsługują ogranicznik pamięci, czyli usługę systemową, która monitoruje i ogranicza wykorzystanie pamięci przez procesy aplikacji za pomocą cgroup w Linuksie w wersji 2. Ogranicznik pamięci zapobiega nadmiernemu wykorzystywaniu pamięci systemowej przez poszczególne aplikacje, co zmniejsza obciążenie pamięci w całym systemie i zapobiega agresywnemu zamykaniu krytycznych procesów z powodu braku pamięci.
Mechanizm
Ogranicznik pamięci jest zintegrowany z usługą Activity Manager Service (AMS), aby śledzić zdarzenia cyklu życia procesu i zmiany stanu. Ogranicznik pamięci wymusza limity pamięci za pomocą systemu plików cgroup v2 jądra systemu Linux.
Aby korzystać z ogranicznika pamięci, jądro urządzenia musi obsługiwać cgroup w wersji 2 i kontroler
memory. Usługa korzysta w szczególności z tych atrybutów:
memory.high- Limit elastyczny. Gdy limit zostanie przekroczony, proces jest ograniczany, a jądro próbuje odzyskać z niego pamięć.
memory.swap.max- Ogranicza ilość miejsca wymiany, z którego może korzystać proces.
Wpływ na aplikacje
Aplikacje, które nie przekraczają limitów pamięci, nie są objęte działaniem ogranicznika pamięci.
Gdy aplikacja przekroczy limit memory.high, jądro usunie z pamięci plikowej dane aplikacji i zastąpi je danymi anonimowymi, aby utrzymać aplikację w ramach limitu. W wyniku usunięcia i zamiany aplikacja może działać wolniej.
W ekstremalnych przypadkach, jeśli aplikacja nadal przydziela pamięć anonimową, a na urządzeniu zabraknie miejsca na wymianę, może jej się nie udać przydzielić pamięci, co prawdopodobnie spowoduje awarię.
Monitorowanie procesów
Ogranicznik pamięci domyślnie monitoruje procesy aplikacji (UID >= 10000). Procesy systemowe są zwykle wyłączone, aby pomóc w weryfikacji stabilności podstawowych funkcji systemu.
Ogranicznik pamięci przypisuje limity pamięci na podstawie stanu procesu:
Widoczne procesy są zauważalne dla użytkownika, np. aktywności na pierwszym planie, usługi na pierwszym planie lub inne stany, w których występuje zacinanie.
Niewidoczne procesy to procesy działające w tle, które nie wchodzą w interakcję z użytkownikiem ani nie są dla niego widoczne.
W tabeli poniżej znajdziesz mapowanie konkretnych stanów procesu na limity pamięci:
| Stan procesu | Limit pamięci |
|---|---|
PERSISTENT | Bez ograniczeń |
PERSISTENT_UI | Bez ograniczeń |
TOP | Widoczne |
BOUND_TOP | Widoczne |
FOREGROUND_SERVICE | Niewidoczne |
BOUND_FOREGROUND_SERVICE | Niewidoczne |
IMPORTANT_FOREGROUND | Widoczne |
IMPORTANT_BACKGROUND | Niewidoczne |
TRANSIENT_BACKGROUND | Niewidoczne |
BACKUP | Niewidoczne |
SERVICE | Niewidoczne |
RECEIVER | Niewidoczne |
TOP_SLEEPING | Widoczne |
HEAVY_WEIGHT | Niewidoczne |
HOME | Niewidoczne |
LAST_ACTIVITY | Niewidoczne |
CACHED_ACTIVITY | W pamięci podręcznej |
CACHED_ACTIVITY_CLIENT | W pamięci podręcznej |
CACHED_RECENT | W pamięci podręcznej |
CACHED_EMPTY | W pamięci podręcznej |
W stanie buforowania procesy są zamrażane, a następnie maksymalnie odzyskiwane.
Gdy proces przekroczy przypisany limit memory.high, narzędzie Memory Limiter wykryje to zdarzenie i może wywołać działania debugowania, takie jak przechwytywanie profilu pamięci lub rejestrowanie anomalii w statsd.
Konfiguracja
Skonfiguruj ogranicznik pamięci za pomocą pliku XML znajdującego się na vendor
partycji. Konfiguracja umożliwia dostosowanie bezwzględnych limitów pamięci na podstawie konkretnych ograniczeń pamięci urządzenia.
Ścieżka pliku:
/vendor/etc/memory-limiter-config.xmlKonfiguracja domyślna: jeśli plik konfiguracji nie zostanie znaleziony lub będzie nieczytelny albo nieprawidłowy, ogranicznik pamięci zostanie wyłączony.
Format XML
Plik konfiguracji jest zgodny ze schematem zdefiniowanym w memory-limiter-config.xsd. Plik umożliwia zdefiniowanie wielu zestawów limitów. Usługa wybiera najlepiej dopasowany zestaw na podstawie dostępnej pamięci RAM urządzenia. Wszystkie wartości pamięci są podawane w mebibajtach (MiB).
<MemoryLimiterConfig>
<version>1</version>
<configList>
<limitSet>
<!-- Limits for a phone with at least 14G of ram: 8G/4G/4G/4G -->
<minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- Dodatnia liczba całkowita identyfikująca wersję konfiguracji. Musi to być 1.
minimumRequiredMemTotal- Minimalna wymagana ilość dostępnej pamięci systemowej, aby ten limit był ważny.
memVisible- Limit pamięci (
memory.high) dozwolony w przypadku widocznych procesów. memNotVisible- Limit pamięci (
memory.high) dozwolony dla niewidocznych procesów. swapVisible- Limit pamięci wymiany (
memory.swap.max) dozwolony w przypadku widocznych procesów. swapNotVisible- Limit wymiany (
memory.swap.max) dozwolony w przypadku niewidocznych procesów.
Wskazówki dotyczące limitu pamięci urządzenia
Podczas konfigurowania limitów pamięci na urządzeniu weź pod uwagę te wytyczne:
Dostosowywanie limitów do możliwości sprzętowych: producenci OEM mogą ustawiać limity dostosowane do możliwości sprzętowych urządzenia. Android zaleca te zakresy:
- Widoczne procesy: co najmniej 1/2 i co najwyżej 2/3 całkowitej pamięci RAM.
- Procesy niewidoczne: od 1/4 do 1/3 całej pamięci RAM. Producenci OEM mogą podejmować różne decyzje w zależności od możliwości urządzenia i przypadków użycia.
Brak interfejsu API środowiska wykonawczego dla aplikacji: od Androida 17 (SDK 37) aplikacje nie mają interfejsu API do sprawdzania limitów pamięci w czasie działania. Producenci OEM powinni wziąć to pod uwagę i unikać ustawiania zbyt niskich limitów, aby aplikacje nie osiągały ich w rozsądnych przypadkach użycia.
Konfiguracja uniwersalna: limity dotyczą wszystkich procesów aplikacji na urządzeniu, w tym aplikacji zainstalowanych fabrycznie. Nie ma listy dozwolonych, która zwalniałaby niektóre aplikacje z tych limitów.
Modyfikowanie konfiguracji
Aby zmienić limity w całym systemie, wykonaj te czynności:
- Modyfikuj
/vendor/etc/memory-limiter-config.xml. - Aby zmiany zaczęły obowiązywać, ponownie uruchom urządzenie lub aplikację
system_server.
Polecenia powłoki
Polecenie am memory-limiter umożliwia Tobie i deweloperom interakcję z usługą w czasie działania na potrzeby tworzenia i testowania:
am memory-limiter <SUB-COMMAND>status
Podpolecenie status podaje stan działania ogranicznika pamięci:
adb shell am memory-limiter statusPrzykładowe dane wyjściowe:
Memory limiter
enabled monitoring=true ignored=none
visibleMem=1948MB visibleSwap=974MB
notVisibleMem=974MB notVisibleSwap=487MB
started=36 watched=36 watch-failed=0
events=0 processes=36 process-hwm=36
Kluczowe pola w danych wyjściowych to:
monitoring- Wskazuje, czy ogranicznik aktywnie monitoruje procesy.
visibleMeminotVisibleMem- Podaj obliczone bezwzględne limity pamięci dla każdego stanu.
events- Liczba przypadków, w których proces przekroczył limit.
processes- Liczba monitorowanych procesów.
ignoruj
Podpolecenie ignore tymczasowo wyklucza identyfikator UID lub wszystkie procesy z ograniczeń. To działanie jest przydatne podczas testów wydajności lub gdy chcesz zezwolić konkretnej aplikacji na przekroczenie limitów.
adb shell am memory-limiter ignore 10087 // Ignore a specific UIDadb shell am memory-limiter ignore all // Ignore all processes (effectively disables limiting)adb shell am memory-limiter ignore none // Resume normal operation
ręczny
Podpolecenie manual zastępuje obliczone limity dla określonego procesu (według identyfikatora procesu lub PID) niestandardową wartością bezwzględną w megabajtach (MB):
adb shell am memory-limiter manual 1234 1024 // Set a 1024 MB limit for PID 1234adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234
Ręczne zastąpienia są stosowane tylko w cyklu życia procesu. Jeśli proces zostanie ponownie uruchomiony, zostaną przywrócone domyślne limity w zależności od stanu.