Demon (lmkd
) Androida do zabijania procesów w przypadku niskiej ilości pamięci monitoruje stan pamięci uruchomionego systemu Androida i reaguje na wysokie obciążenie pamięci, zabijając procesy o najmniejszym znaczeniu, aby zachować akceptowalny poziom wydajności systemu.
Informacje o obciążeniu pamięci
System Android, który równolegle wykonuje wiele procesów, może napotkać sytuacje, gdy wyczerpuje się pamięć systemowa, a procesy wymagające więcej pamięci mogą odczuwać zauważalne opóźnienia. Napięcie pamięci to stan, w którym systemowi brakuje pamięci. Aby zmniejszyć to napięcie, Android musi zwolnić pamięć, na przykład przez ograniczenie lub zamykanie nieistotnych procesów, żądanie zwolnienia nieistotnych zasobów z pamięci podręcznej itp.
Wcześniej Android monitorował obciążenie pamięci systemowej za pomocą sterownika LMK (low memory killer) działającego w rdzeniu. Jest to sztywny mechanizm, który zależy od zakodowanych na stałe wartości. Od jądra 4.12 sterownik LMK został usunięty z upstreamowego jądra, a zadania monitorowania pamięci i zabijania procesów wykonuje przestrzeń użytkownika lmkd
.
Informacje o zatrzymaniu spowodowanym przez spadek ciśnienia
Android 10 i nowsze wersje obsługują nowy tryb lmkd
, który wykorzystuje monitory PSI (pressure stall information) jądra do wykrywania nacisku pamięci. Zestaw poprawek PSI w rdzeniach upstream (przeniesionych do wersji 4.9 i 4.14) mierzy czas opóźnienia zadań spowodowany brakiem pamięci. Te opóźnienia mają bezpośredni wpływ na wrażenia użytkownika, dlatego stanowią wygodny wskaźnik do określania stopnia obciążenia pamięci. Kernel upstream zawiera też monitory PSI, które umożliwiają uprzywilejowanym procesom w przestrzeni użytkownika (takim jak lmkd
) określanie wartości progowych opóźnień i subskrybowanie zdarzeń z jądra w przypadku przekroczenia wartości progowych.
Różnica między monitorowaniem PSI a vmpressure
Ponieważ sygnały vmpressure
(generowane przez jądro do wykrywania ciśnienia w pamięci i używane przez lmkd
) często zawierają wiele fałszywych wyników pozytywnych, lmkd
musi przeprowadzić filtrowanie, aby określić, czy pamięć jest pod prawdziwym ciśnieniem.
Powoduje to niepotrzebne lmkd
budzenia i używanie dodatkowych zasobów obliczeniowych. Korzystanie z monitorowania PSI skutkuje dokładniejszym wykrywaniem ciśnienia pamięci i minimalizacją narzutu związanego z filtrowaniem.
Korzystanie z monitorów PSI
Aby zamiast zdarzeń vmpressure
używać monitorów PSI, skonfiguruj właściwość ro.lmk.use_psi
. Wartość domyślna to true
, co powoduje, że PSI monitoruje domyślny mechanizm wykrywania nacisku pamięci dla lmkd
. Monitory PSI wymagają obsługi przez jądro, dlatego jądro musi zawierać poprawki PSI i być skompilowane z włączoną obsługą PSI (CONFIG_PSI=y
).
Wady sterownika LMK w rdzeniu
Android wycofuje sterownik LMK z powodu kilku problemów, w tym:
- Urządzenia z małą ilością pamięci RAM wymagały agresywnego dostosowania, a nawet wtedy pracowały słabo w przypadku zadań z dużą aktywną pamięcią podręczną pagecache obsługiwaną przez pliki. Złe wyniki spowodowały utratę kontroli i brak zabójstw.
- Sterownik jądra LMK korzystał z limitów wolnej pamięci bez skalowania na podstawie obciążenia pamięci.
- Ze względu na sztywność projektu partnerzy często dostosowywali sterownik, aby działał na ich urządzeniach.
- Sterownik LMK był podłączony do interfejsu API do kompresji bloków, który nie był przeznaczony do wykonywania czasochłonnych operacji, takich jak wyszukiwanie celów i ich zabijanie, co spowalniało proces
vmscan
.
Userspace lmkd
Przestrzeń użytkownika lmkd
realizuje te same funkcje co sterownik w jądrze, ale do wykrywania i szacowania obciążenia pamięci używa istniejących mechanizmów jądra. Takie mechanizmy obejmują korzystanie ze zdarzeń generowanych przez jądro vmpressure
lub monitorów informacji o ciśnieniu (PSI) w celu otrzymywania powiadomień o poziomie ciśnienia w pamięci. Obejmują one też korzystanie z funkcji cgroup pamięci w celu ograniczenia zasobów pamięci przydzielonych do każdego procesu na podstawie jego ważności.
Używanie lmkd w przestrzeni użytkownika w Androidzie 10
W Androidzie 9 i nowszych przestrzeń użytkownika lmkd
jest aktywowana, jeśli nie wykryto sterownika LMK w rdzeniu. Ponieważ przestrzeń użytkownika lmkd
wymaga obsługi cgroup przez jądro, jądro musi zostać skompilowane z tymi ustawieniami konfiguracji:
CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
Zabijanie strategii
Userspace lmkd
obsługuje strategie zabijania na podstawie zdarzeń vmpressure
lub monitorów PSI, ich ważności i innych wskazówek, takich jak wykorzystanie swapa. Strategie zabijania różnią się w zależności od tego, czy urządzenie ma mało pamięci czy dużą wydajność:
- Na urządzeniach z małą ilością pamięci system powinien tolerować wyższe wykorzystanie pamięci jako normalny tryb działania.
- Na urządzeniach o wysokiej wydajności wykorzystanie pamięci należy traktować jako nieprawidłową sytuację i usuwać, zanim wpłynie na ogólną wydajność.
Strategię wykluczania możesz skonfigurować za pomocą usługi ro.config.low_ram
.
Userspace lmkd
obsługuje też tryb starszy, w którym podejmuje decyzje o zatrzymaniu procesu, używając tych samych strategii co sterownik LMK w rdzeniu (czyli progów wolnej pamięci i pliku pamięci podręcznej). Aby włączyć tryb starszy, ustaw właściwość ro.lmk.use_minfree_levels
na true
.
Konfigurowanie lmkd
Skonfiguruj lmkd
na konkretnym urządzeniu, używając tych właściwości.
Właściwość | Użyj | Domyślny |
---|---|---|
ro.config.low_ram
|
Określ, czy urządzenie ma małą ilość pamięci RAM, czy jest to urządzenie o wysokiej wydajności. | false
|
ro.lmk.use_psi |
Używaj monitorów PSI (zamiast zdarzeń vmpressure ). |
true |
ro.lmk.use_minfree_levels
|
Używaj progów wolnej pamięci i pliku pamięci podręcznej do podejmowania decyzji o zakończeniu procesu (czyli dopasowywania funkcji do jądra sterownika LMK). | false
|
ro.lmk.low
|
Minimalna wartość oom_adj procesów kwalifikujących się do zabijania na poziomie vmpressure .
|
1001 (wyłączona) |
ro.lmk.medium
|
Minimalny wynik oom_adj procesów kwalifikujących się do zabijania na średnim poziomie vmpressure .
|
800 (przechowywane w pamięci podręcznej lub nieistotne usługi) |
ro.lmk.critical
|
Minimalny wynik oom_adj procesów kwalifikujących się do zabijania na poziomie krytycznym vmpressure .
|
0 (dowolny proces) |
ro.lmk.critical_upgrade
|
Włącz uaktualnienie do poziomu krytycznego. | false
|
ro.lmk.upgrade_pressure
|
Maksymalna liczba mem_pressure , przy której poziom jest ulepszany, ponieważ system zbyt często przełącza się między poziomami.
|
100 (wyłączona) |
ro.lmk.downgrade_pressure
|
Minimalna wartość mem_pressure , przy której zdarzenie vmpressure jest ignorowane, ponieważ nadal jest wystarczająco dużo wolnej pamięci.
|
100 (wyłączona) |
ro.lmk.kill_heaviest_task
|
Zatrzymanie najbardziej obciążającego zadania (najlepsza decyzja) w porównaniu z dowolnym innym zadaniem (szybka decyzja). | false
|
ro.lmk.kill_timeout_ms
|
Czas w milisekundach po zabiciu, po którym nie będzie dokonywane żadne dodatkowe zabicie. | 0 (wyłączona) |
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
LMKD w przestrzeni użytkownika w Androidzie 11
Android 11 ulepsza lmkd
, wprowadzając nową strategię zabijania procesów. Strategia zabijania używa mechanizmu PSI do wykrywania nacisku na pamięć, który został wprowadzony w Androidzie 10. lmkd
w Androidzie 11 uwzględnia poziomy wykorzystania zasobów pamięci i throttlingu, aby zapobiec niedoborowi pamięci i pogorszeniu wydajności.
Ta strategia zastępuje poprzednie strategie i może być stosowana zarówno na urządzeniach o wysokiej wydajności, jak i na urządzeniach z małą ilością pamięci RAM (Android Go).
Wymagania dotyczące jądra
W przypadku urządzeń z Androidem 11 lmkd
wymaga tych funkcji jądra:
- Dołącz poprawki PSI i włącz PSI (backporty dostępne w powszechnie używanych jądrach Androida 4.9, 4.14 i 4.19).
- Dołącz poprawki dotyczące obsługi PIDFD (poprawki dostępne w jądrach wspólnych Androida w wersjach 4.9, 4.14 i 4.19).
- W przypadku urządzeń z małą ilością pamięci RAM uwzględnij grupy pamięci.
jądro musi być skompilowane z tymi ustawieniami konfiguracji:
CONFIG_PSI=y
Konfigurowanie lmkd w Androidzie 11
Strategia zabijania pamięci w Androidzie 11 obsługuje ustawienia 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.
Właściwość | Użyj | Domyślny | |
---|---|---|---|
Wysoka wydajność | Mała ilość pamięci RAM | ||
ro.lmk.psi_partial_stall_ms |
Próg częściowego zablokowania PSI (w milisekundach) dla powiadomienia o niskiej pamięci. Jeśli urządzenie otrzymuje powiadomienia o nadmiarze pamięci zbyt późno, zmniejsz tę wartość, aby powiadomienia były wysyłane wcześniej. Jeśli powiadomienia o nadmiarowym ciśnieniu są niepotrzebnie aktywowane, zwiększ tę wartość, aby zmniejszyć wrażliwość urządzenia na hałas. | 70 |
200 |
ro.lmk.psi_complete_stall_ms |
Całkowity próg zablokowania PSI (w milisekundach) do wywołania powiadomień o krytycznym wykorzystaniu pamięci. Jeśli urządzenie otrzymuje powiadomienia o krytycznym poziomie pamięci zbyt późno, zmniejsz tę wartość, aby powiadomienia były wysyłane wcześniej. Jeśli powiadomienia o krytycznym obciążeniu pamięci są niepotrzebnie aktywowane, zwiększ tę wartość, aby zmniejszyć wrażliwość urządzenia na hałas. | 700 |
|
ro.lmk.thrashing_limit |
Maksymalna liczba refaultów zbioru roboczego w procentach z łącznego rozmiaru pamięci podręcznej obsługiwanej przez plik. Wartości większe od tej wartości oznaczają, że system uważa, że jego pamięć podręczna jest przeciążona. Jeśli wydajność urządzenia jest ograniczona z powodu obciążenia pamięci, zmniejsz tę wartość, aby ograniczyć thrashing. Jeśli wydajność urządzenia jest niepotrzebnie obniżana z powodu thrashingu, zwiększ wartość, aby zezwolić na większą ilość thrashingu. | 100 |
30 |
ro.lmk.thrashing_limit_decay |
Zmniejszenie progu tłoczenia wyrażone w procentach pierwotnego progu służącego do obniżenia progu, gdy system nie wraca do normy nawet po zabiciu. Jeśli ciągłe stosowanie funkcji thrashing powoduje niepotrzebne zabijanie procesów, zmniejsz tę wartość. Jeśli reakcja na ciągłe tłoczenie po zabiciu jest zbyt wolna, zwiększ wartość. | 10 |
50 |
ro.lmk.swap_util_max |
Maksymalna ilość pamięci podręcznej jako procent łącznej pamięci, którą można zamienić. Gdy ilość pamięci wymiennej przekroczy ten limit, oznacza to, że system przełączył większość pamięci wymiennej i nadal jest obciążony.
Może się to zdarzyć, gdy alokacje, których nie można zamienić, powodują wzrost zapotrzebowania na pamięć, którego nie można zmniejszyć przez zamianę, ponieważ większość pamięci, którą można zamienić, jest już zamieniona. Wartość domyślna to 100, co w efekcie wyłącza to sprawdzanie. Jeśli wydajność urządzenia jest niska podczas presji pamięci, a wykorzystanie podmiany jest wysokie i poziom wolnej podmiany nie spada do ro.lmk.swap_free_low_percentage , zmniejsz tę wartość, aby ograniczyć wykorzystanie podmiany. |
100 |
100 |
W przypadku nowej strategii wygaszania obowiązują te same ustawienia, co w przypadku starszych strategii.
Właściwość | Użyj | Domyślny | |
---|---|---|---|
Wysoka wydajność | Mała ilość pamięci RAM | ||
ro.lmk.swap_free_low_percentage |
Poziom bezpłatnego przełączania jako odsetek całkowitego miejsca na wymianę. Funkcja `lmkd` używa tej wartości jako progu, po przekroczeniu którego system uznaje, że brakuje mu miejsca na dysku. Jeśli `lmkd` zabija, gdy jest zbyt dużo miejsca na wymianie, zmniejsz odsetek. Jeśli zabijanie przez `lmkd` następuje zbyt późno, co pozwala na zabijanie przez OOM, zwiększ ten odsetek. | 20 |
10 |
ro.lmk.debug |
Spowoduje to włączenie dzienników debugowania `lmkd`. Włącz debugowanie podczas strojenia. | false |