Proces demona niskiego poziomu pamięci w systemie Android ( lmkd
) monitoruje stan pamięci działającego systemu Android i reaguje na wysokie zużycie pamięci, zabijając najmniej istotne procesy, aby utrzymać działanie systemu na akceptowalnym poziomie.
O presji pamięci
System Android działający równolegle z wieloma procesami może napotkać sytuacje, w których pamięć systemowa jest wyczerpana, a procesy wymagające większej ilości pamięci doświadczają zauważalnych opóźnień. Ciśnienie pamięci , stan, w którym systemowi brakuje pamięci, wymaga od systemu Android zwolnienia pamięci (w celu złagodzenia presji) przez ograniczanie lub zabijanie nieistotnych procesów, żądanie zwolnienia niekrytycznych zasobów z pamięci podręcznej i tak dalej.
Historycznie rzecz biorąc, Android monitorował ciśnienie pamięci systemowej za pomocą wbudowanego w jądro sterownika niskiego poziomu pamięci (LMK), sztywnego mechanizmu, który zależy od wartości zakodowanych na stałe. Począwszy od jądra 4.12, sterownik LMK jest usuwany z jądra nadrzędnego, a przestrzeń użytkownika lmkd
wykonuje zadania monitorowania pamięci i zabijania procesów.
Informacje o stajni ciśnieniowej
Android 10 i nowsze obsługują nowy tryb lmkd
, który używa monitorów informacji o utknięciu ciśnienia jądra (PSI) do wykrywania ciśnienia w pamięci. Zestaw poprawek PSI w jądrze nadrzędnym (przeniesiony do jąder 4.9 i 4.14) mierzy ilość czasu, o jaką zadania są opóźnione w wyniku braku pamięci. Ponieważ te opóźnienia bezpośrednio wpływają na wrażenia użytkownika, stanowią wygodną metrykę do określania wagi presji pamięci. Nadrzędne jądro zawiera również monitory PSI, które umożliwiają uprzywilejowanym procesom w przestrzeni użytkownika (takim jak lmkd
) określanie progów dla tych opóźnień i subskrybowanie zdarzeń z jądra w przypadku przekroczenia progu.
Monitory PSI a sygnały vmpressure
Ponieważ sygnały vmpressure
(generowane przez jądro do wykrywania obciążenia pamięci i używane przez lmkd
) często zawierają wiele fałszywych alarmów, lmkd
musi przeprowadzić filtrowanie, aby określić, czy pamięć jest pod rzeczywistym obciążeniem. Powoduje to niepotrzebne lmkd
i użycie dodatkowych zasobów obliczeniowych. Korzystanie z monitorów PSI zapewnia dokładniejsze wykrywanie nacisku pamięci i minimalizuje koszty filtrowania.
Korzystanie z monitorów PSI
Aby używać monitorów PSI zamiast zdarzeń vmpressure
, skonfiguruj właściwość ro.lmk.use_psi
. Wartość domyślna to true
, dzięki czemu monitory PSI są domyślnym mechanizmem wykrywania nacisku pamięci dla lmkd
. Ponieważ monitory PSI wymagają obsługi jądra, jądro musi zawierać poprawki backportu PSI i być skompilowane z włączoną obsługą PSI ( CONFIG_PSI=y
).
Wady wbudowanego sterownika LMK
Android wycofuje sterownik LMK z powodu wielu problemów, w tym:
- Urządzenia o małej ilości pamięci RAM musiały być agresywnie dostrajane, a nawet wtedy działałyby słabo w przypadku obciążeń z dużym, aktywnym buforem stron opartym na plikach. Słaba wydajność spowodowała thrashowanie i brak zabójstw.
- Sterownik jądra LMK opierał się na limitach wolnej pamięci, bez skalowania opartego na obciążeniu pamięci.
- Ze względu na sztywność konstrukcji partnerzy często dostosowywali sterownik tak, aby działał na ich urządzeniach.
- Sterownik LMK podłączył się do interfejsu API zmniejszania slabów, który nie został zaprojektowany do ciężkich operacji, takich jak wyszukiwanie celów i ich zabijanie, co spowolniło proces
vmscan
.
Przestrzeń użytkownika
Przestrzeń użytkownika lmkd
implementuje tę samą funkcjonalność co sterownik wbudowany w jądro, ale wykorzystuje istniejące mechanizmy jądra do wykrywania i szacowania obciążenia pamięci. Takie mechanizmy obejmują używanie generowanych przez jądro zdarzeń vmpressure
lub monitorów informacji o zatrzymaniu ciśnienia (PSI) w celu otrzymywania powiadomień o poziomach ciśnienia pamięci oraz używanie funkcji pamięci cgroup w celu ograniczenia zasobów pamięci przydzielonych każdemu procesowi na podstawie ważności procesu.
Korzystanie z lmkd w przestrzeni użytkownika w systemie Android 10
W systemie Android 9 i nowszych lmkd
w przestrzeni użytkownika aktywuje się, jeśli sterownik LMK w jądrze nie zostanie wykryty. Ponieważ userspace lmkd
wymaga obsługi jądra dla cgroups pamięci, jądro musi być skompilowane z następującymi ustawieniami konfiguracyjnymi:
CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
Strategie zabijania
lmkd
obsługuje strategie kill oparte na zdarzeniach vmpressure
lub monitorach PSI, ich ważności i innych wskazówkach, takich jak wykorzystanie wymiany. Strategie zabijania różnią się między urządzeniami o małej ilości pamięci i urządzeniami o wysokiej wydajności:
- Na urządzeniach o małej ilości pamięci system powinien tolerować wyższe zużycie pamięci jako normalny tryb działania.
- Na urządzeniach o wysokiej wydajności ciśnienie pamięci powinno być postrzegane jako sytuacja nienormalna i naprawione, zanim wpłynie na ogólną wydajność.
Strategię zabijania można skonfigurować za pomocą właściwości ro.config.low_ram
. Aby uzyskać szczegółowe informacje, zobacz Konfiguracja z niskim suwakiem .
lmkd
w przestrzeni użytkownika obsługuje również tryb starszej wersji, w którym podejmuje decyzje o zabiciu przy użyciu tych samych strategii, co sterownik LMK w jądrze (czyli progi wolnej pamięci i pamięci podręcznej plików). Aby włączyć tryb starszej wersji, ustaw właściwość ro.lmk.use_minfree_levels
na true
.
Konfiguracja lmkd
Skonfiguruj lmkd
dla określonego urządzenia, korzystając z następujących właściwości.
Nieruchomość | Posługiwać się | Domyślna |
---|---|---|
ro.config.low_ram | Określ, czy urządzenie jest urządzeniem o małej ilości pamięci RAM, czy o wysokiej wydajności. | false |
ro.lmk.use_psi | Użyj monitorów PSI (zamiast zdarzeń vmpressure ). | true |
ro.lmk.use_minfree_levels | Użyj progów wolnej pamięci i pamięci podręcznej plików do podejmowania decyzji o zakończeniu procesu (czyli dopasuj funkcjonalność wbudowanego w jądro sterownika LMK). | false |
ro.lmk.low | Minimalny wynik oom_adj dla procesów kwalifikujących się do zabicia na niskim poziomie vmpressure . | 1001 (wyłączony) |
ro.lmk.medium | Minimalny wynik oom_adj dla procesów kwalifikujących się do zabicia na średnim poziomie vmpressure . | 800 (usługi z pamięci podręcznej lub nieistotne) |
ro.lmk.critical | Minimalny wynik oom_adj dla procesów kwalifikujących się do zabicia na krytycznym poziomie vmpressure . | 0 (dowolny proces) |
ro.lmk.critical_upgrade | Włącz aktualizację do poziomu krytycznego. | false |
ro.lmk.upgrade_pressure | Maksymalna wartość mem_pressure , przy której poziom jest aktualizowany, ponieważ system za bardzo się zmienia. | 100 (wyłączony) |
ro.lmk.downgrade_pressure | Minimalna wartość mem_pressure , przy której zdarzenie vmpressure jest ignorowane, ponieważ wciąż dostępna jest wystarczająca ilość wolnej pamięci. | 100 (wyłączony) |
ro.lmk.kill_heaviest_task | Zabij najcięższe kwalifikujące się zadanie (najlepsza decyzja) w porównaniu z dowolnym kwalifikującym się zadaniem (szybka decyzja). | true |
ro.lmk.kill_timeout_ms | Czas trwania w milisekundach po zabiciu, gdy nie zostanie wykonane żadne dodatkowe zabójstwo. | 0 (wyłączony) |
ro.lmk.debug | Włącz dzienniki debugowania lmkd . | false |
Przykładowa konfiguracja urządzenia:
PRODUCT_PROPERTY_OVERRIDES += \
ro.lmk.low=1001 \
ro.lmk.medium=800 \
ro.lmk.critical=0 \
ro.lmk.critical_upgrade=false \
ro.lmk.upgrade_pressure=100 \
ro.lmk.downgrade_pressure=100 \
ro.lmk.kill_heaviest_task=true
Przestrzeń użytkownika lmkd w Androidzie 11
Android 11 ulepsza lmkd
, wprowadzając nową strategię zabijania. Strategia zabijania wykorzystuje mechanizm PSI do wykrywania nacisku pamięci wprowadzony w systemie Android 10. lmkd
w systemie Android 11 uwzględnia poziomy wykorzystania zasobów pamięci i thrashing, aby zapobiec głodowi pamięci i pogorszeniu wydajności. Ta strategia zabijania zastępuje poprzednie strategie i może być używana zarówno na urządzeniach o wysokiej wydajności, jak io małej ilości pamięci RAM (Android Go).
Wymagania jądra
W przypadku urządzeń z systemem Android 11 lmkd
wymaga następujących funkcji jądra:
- Dołącz łatki PSI i włącz PSI (backporty dostępne w popularnych jądrach Androida 4.9, 4.14 i 4.19).
- Dołącz poprawki obsługujące PIDFD (backporty dostępne w popularnych jądrach Androida 4.9, 4.14 i 4.19).
- W przypadku urządzeń z małą ilością pamięci RAM należy uwzględnić cgroups pamięci.
Jądro musi być skompilowane z następującymi ustawieniami konfiguracyjnymi:
CONFIG_PSI=y
Konfiguracja lmkd w Androidzie 11
Strategia zabijania pamięci w systemie Android 11 obsługuje pokrętła strojenia i wartości domyślne wymienione poniżej. Te funkcje działają zarówno na urządzeniach o wysokiej wydajności, jak i na urządzeniach z małą ilością pamięci RAM.
Nieruchomość | Posługiwać się | Domyślna | |
---|---|---|---|
Wysoka wydajność | Niska pamięć RAM | ||
ro.lmk.psi_partial_stall_ms | Próg częściowego utknięcia PSI w milisekundach do wyzwalania powiadomienia o małej ilości pamięci. Jeśli urządzenie zbyt późno otrzymuje powiadomienia o obciążeniu pamięci, zmniejsz tę wartość, aby wyzwolić wcześniejsze powiadomienia. Jeśli powiadomienia o obciążeniu pamięci są uruchamiane niepotrzebnie, zwiększ tę wartość, aby urządzenie było mniej wrażliwe na hałas. | 70 | 200 |
ro.lmk.psi_complete_stall_ms | Całkowity próg utknięcia PSI (w milisekundach) do wyzwalania krytycznych powiadomień dotyczących pamięci. Jeśli urządzenie zbyt późno otrzymuje powiadomienia o krytycznym obciążeniu pamięci, zmniejsz tę wartość, aby wyzwolić wcześniejsze powiadomienia. Jeśli powiadomienia o krytycznym ciśnieniu pamięci są wyzwalane niepotrzebnie, zwiększ tę wartość, aby urządzenie było mniej wrażliwe na hałas. | 700 | |
ro.lmk.thrashing_limit | Maksymalna liczba błędów zestawu roboczego jako procent całkowitego rozmiaru pamięci podręcznej stron z plikami. Błędy zestawu roboczego powyżej tej wartości oznaczają, że system jest uważany za przeczyszczający swoją pamięć podręczną stron. Jeśli wydajność urządzenia ma wpływ na obciążenie pamięci, zmniejsz wartość, aby ograniczyć thrashing. Jeśli wydajność urządzenia zostanie niepotrzebnie obniżona z powodu thrashingu, zwiększ wartość, aby umożliwić więcej thrashingu. | 100 | 30 |
ro.lmk.thrashing_limit_decay | Zanik progu thrashowania wyrażony jako procent pierwotnego progu używany do obniżenia progu, gdy system nie działa, nawet po zabiciu. Jeśli ciągłe thrashowanie powoduje niepotrzebne zabójstwa, zmniejsz wartość. Jeśli reakcja na ciągłe thrashowanie po zabójstwie jest zbyt wolna, zwiększ wartość. | 10 | 50 |
ro.lmk.swap_util_max | Maksymalna ilość wymienianej pamięci jako procent całkowitej ilości wymienianej pamięci. Gdy wymieniana pamięć przekroczy ten limit, oznacza to, że system zamienił większość swojej wymiennej pamięci i nadal jest pod presją. Może się to zdarzyć, gdy alokacje niewymienialne generują ciśnienie pamięci, którego nie można złagodzić przez zamianę, ponieważ większość pamięci wymiennej jest już zamieniona. Wartość domyślna to 100, co skutecznie wyłącza to sprawdzenie. Jeśli wydajność urządzenia ma wpływ na ciśnienie pamięci, gdy wykorzystanie wymiany jest wysokie, a poziom bezpłatnej wymiany nie spada do ro.lmk.swap_free_low_percentage , zmniejsz wartość, aby ograniczyć wykorzystanie wymiany. | 100 | 100 |
Poniższe stare pokrętła strojenia działają również z nową strategią zabijania.
Nieruchomość | Posługiwać się | Domyślna | |
---|---|---|---|
Wysoka wydajność | Niska pamięć RAM | ||
ro.lmk.swap_free_low_percentage | Poziom wolnej wymiany jako procent całkowitej przestrzeni wymiany. `lmkd` używa tej wartości jako progu, kiedy należy uznać system za brak przestrzeni wymiany. Jeśli `lmkd` zabije, gdy w swapie jest za dużo miejsca, zmniejsz procent. Jeśli zabójstwa `lmkd` zdarzają się zbyt późno, co pozwala na zabijanie przez OOM, zwiększ procent. | 20 | 10 |
ro.lmk.debug | Włącza to dzienniki debugowania `lmkd`. Włącz debugowanie podczas strojenia. | false |