Demon (lmkd
) Androida do zabijania procesów przy niskim poziomie pamięci monitoruje stan pamięci działającego systemu Androida i reaguje na wysokie obciążenie pamięci, zabijając procesy o najmniejszym znaczeniu, aby zachować akceptowalne osiągiwanie przez system.
Informacje o obciążeniu pamięci
W przypadku systemu Android uruchamianego równolegle mogą wystąpić sytuacje, gdy pamięć systemu się wyczerpie, a procesy wymagające więcej pamięci będą zauważalne opóźnienia. Wykorzystanie pamięci, czyli stan, w którym system ma za mało pamięci, wymaga od Androida zwolnienia pamięci (aby zmniejszyć presję) przez ograniczanie lub zatrzymywanie nieistotnych procesów, wysyłanie żądań do procesów zwalniania niekrytycznych zasobów zapisanych w 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 budynku ciśnieniowym
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 (przeniesiony do wersji 4.9 i 4.14) mierzy czas opóźnienia zadań spowodowany brakiem pamięci. Opóźnienia te bezpośrednio wpływają na wygodę użytkowników, dlatego są one wygodnym wskaźnikiem poziomu wykorzystania 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 kernela, gdy zostanie przekroczona wartość progowa.
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łszywie pozytywnych wyników, lmkd
musi przeprowadzić filtrowanie, aby określić, czy pamięć jest pod prawdziwym ciśnieniem.
Powoduje to niepotrzebne lmkd
wybudzanie i używanie dodatkowych zasobów obliczeniowych. Korzystanie z monitorowania PSI skutkuje dokładniejszym wykrywaniem ciśnienia pamięci i minimalizuje nakłady związane z filtrowaniem.
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
, co oznacza, że PSI monitoruje domyślny mechanizm wykrywania wykorzystania pamięci w lmkd
. Monitory PSI wymagają obsługi przez jądro, dlatego jądro musi zawierać łaty do wstecznego przenoszenia PSI i być skompilowane z włączoną obsługą PSI (CONFIG_PSI=y
).
Wady sterownika LMK umieszczonego w jądrze
Android wycofuje sterownik LMK z powodu szeregu problemów, takich jak:
- 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ść konstrukcji partnerzy często dostosowali przetwornik tak, aby działał na ich urządzeniach.
- Sterownik LMK był podłączony do interfejsu API Shrinker, który nie został zaprojektowany z myślą o intensywnych operacjach, takich jak wyszukiwanie i 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 z generowanych przez jądro zdarzeń vmpressure
lub monitorów informacji o zatrzymaniu z powodu braku zasobów (PSI), aby otrzymywać powiadomienia o poziomie zasobów pamięci, oraz korzystanie z funkcji cgroup pamięci, aby ograniczyć zasoby pamięci przydzielone poszczególnym procesom na podstawie ich 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, należy skompilować jądro z tymi ustawieniami konfiguracji:
CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
Strategie zabijania
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ę wycofania możesz skonfigurować za pomocą usługi ro.config.low_ram
. Więcej informacji znajdziesz w sekcji Konfiguracja z małą ilością pamięci 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 urządzeniem 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 pamięci podręcznej plików do podejmowania decyzji o zakończeniu procesów (czyli dopasowanych do funkcjonalności sterownika LMK znajdującego się w jądrze). | false
|
ro.lmk.low
|
Minimalny wynik oom_adj procesów kwalifikujących się do zakończenia na niskim poziomie vmpressure .
|
1001 (wyłączony) |
ro.lmk.medium
|
Minimalny wynik oom_adj procesów kwalifikujących się do zakończenia na średnim poziomie vmpressure .
|
800 (usługi w pamięci podręcznej lub usługi niepotrzebne) |
ro.lmk.critical
|
Minimalny wynik oom_adj procesów, które mogą zostać przerwane 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 wykorzystuje obecny w Androidzie 10 mechanizm PSI do wykrywania wykorzystania pamięci. lmkd
w Androidzie 11 uwzględnia poziomy wykorzystania zasobów pamięci i szyfrowanie, co zapobiega wyczerpaniu się 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 jądra systemu
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).
- Uwzględnij poprawki obsługujące PIDFD (porty dostępne w typowych jądrach Androida 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 LDAP 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ło 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 ograniczana z powodu thrashingu, zwiększ wartość, aby umożliwić więcej thrashingu. | 100 |
30 |
ro.lmk.thrashing_limit_decay |
Spadek progu rzutów wyrażony jako procent pierwotnego progu użytego do obniżenia progu, gdy system nie wróci do zdrowia 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 twarde uderzenia 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 swapa jest wysokie i poziom wolnego swapa nie spada do ro.lmk.swap_free_low_percentage , zmniejsz tę wartość, aby ograniczyć wykorzystanie swapa. |
100 |
100 |
W przypadku nowej strategii wygaszania działają też te stare ustawienia.
Właściwość | Użyj | Domyślny | |
---|---|---|---|
Wysoka wydajność | Mała ilość pamięci RAM | ||
ro.lmk.swap_free_low_percentage |
Poziom wolnego miejsca na wymianę jako procent 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 parametr „lmkd” zakończy działanie z powodu zbyt dużej ilości miejsca w wymianie, zmniejsz tę wartość procentową. 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 logów debugowania „lmkd”. Włącz debugowanie podczas dostrajania. | false |