Demon zabójcy małej ilości pamięci

Proces demona niskiego poziomu pamięci systemu Android ( lmkd ) monitoruje stan pamięci działającego systemu Android i reaguje na duże obciążenie pamięci, zabijając najmniej istotne procesy, aby utrzymać wydajność systemu na akceptowalnym poziomie.

O presji pamięci

W systemie Android uruchamiającym wiele procesów równolegle mogą wystąpić 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 , czyli stan, w którym w systemie zaczyna brakować pamięci, wymaga od Androida zwolnienia pamięci (aby złagodzić obciążenie) poprzez ograniczanie lub kończenie nieistotnych procesów, żądanie od procesów zwolnienia niekrytycznych zasobów z pamięci podręcznej i tak dalej.

Historycznie rzecz biorąc, system Android monitorował ciśnienie pamięci systemowej za pomocą wbudowanego w jądro sterownika Low Memory Killer (LMK) – sztywnego mechanizmu zależnego od zakodowanych na stałe wartości. Począwszy od jądra 4.12, sterownik LMK został usunięty z jądra nadrzędnego, a lmkd w przestrzeni użytkownika wykonuje zadania monitorowania pamięci i zabijania procesów.

Informacje o przestoju ciśnieniowym

Android 10 i nowsze wersje obsługują nowy tryb lmkd , który wykorzystuje monitory informacji o przestoju jądra (PSI) do wykrywania ciśnienia pamięci. Zestaw poprawek PSI w jądrze nadrzędnym (przeniesiony do jąder 4.9 i 4.14) mierzy ilość czasu, o jaki zadania są opóźnione w wyniku niedoborów pamięci. Ponieważ te opóźnienia bezpośrednio wpływają na wygodę użytkownika, stanowią wygodną metrykę do określania dotkliwości wykorzystania pamięci. Jądro nadrzędne zawiera również monitory PSI, które umożliwiają procesom uprzywilejowanej przestrzeni użytkownika (takim jak lmkd ) określenie progów dla tych opóźnień i subskrybowanie zdarzeń z jądra w przypadku przekroczenia progu.

Monitory PSI w porównaniu z sygnałami ciśnienia vm

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 wybudzanie lmkd i użycie dodatkowych zasobów obliczeniowych. Korzystanie z monitorów PSI zapewnia dokładniejsze wykrywanie obciążenia pamięci i minimalizuje obciążenie 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 powoduje, że PSI monitoruje domyślny mechanizm wykrywania obciążenia 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 z małą ilością pamięci RAM musiały być agresywnie dostrajane, a nawet wtedy słabo radziły sobie z obciążeniami z aktywną pamięcią podręczną opartą na dużych plikach. Słabe wyniki spowodowały bicie i brak zabójstw.
  • Sterownik jądra LMK opierał się na limitach wolnej pamięci, bez skalowania w oparciu o wykorzystanie 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 API modułu zmniejszania płyt, który nie był przeznaczony do ciężkich operacji, takich jak wyszukiwanie celów i zabijanie ich, co spowalniało proces vmscan .

Przestrzeń użytkownika lmkd

lmkd przestrzeni użytkownika implementuje tę samą funkcjonalność, co sterownik wbudowany w jądro, ale wykorzystuje istniejące mechanizmy jądra do wykrywania i szacowania wykorzystania pamięci. Takie mechanizmy obejmują wykorzystanie generowanych przez jądro zdarzeń vmpressure lub monitorów informacji o przeciągnięciu ciśnienia (PSI) w celu uzyskania powiadomień o poziomach wykorzystania pamięci oraz wykorzystanie funkcji cgroup pamięci w celu ograniczenia zasobów pamięci przydzielanych każdemu procesowi na podstawie ważności procesu.

Korzystanie z przestrzeni użytkownika lmkd w Androidzie 10

W systemie Android 9 i nowszych wersjach lmkd przestrzeni użytkownika jest aktywowany, jeśli nie zostanie wykryty wbudowany w jądro sterownik LMK. Ponieważ lmkd przestrzeni użytkownika wymaga obsługi przez jądro cgrup pamięci, jądro musi zostać skompilowane z następującymi ustawieniami konfiguracyjnymi:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Strategie zabijania

lmkd przestrzeni użytkownika obsługuje strategie zabijania oparte na zdarzeniach vmpressure lub monitorach PSI, ich ważności i innych wskazówkach, takich jak wykorzystanie wymiany. Strategie zabijania różnią się w przypadku urządzeń o małej ilości pamięci i urządzeniach o wysokiej wydajności:

  • Na urządzeniach o małej ilości pamięci system powinien tolerować większe wykorzystanie pamięci w normalnym trybie działania.
  • Na urządzeniach o wysokiej wydajności obciążenie pamięci należy postrzegać jako sytuację nienormalną i naprawiać je, zanim wpłynie to na ogólną wydajność.

Możesz skonfigurować strategię zabijania za pomocą właściwości ro.config.low_ram . Aby uzyskać szczegółowe informacje, zobacz Konfiguracja małej ilości pamięci RAM .

lmkd przestrzeni użytkownika obsługuje także starszy tryb, w którym podejmuje decyzje o zakończeniu działania, korzystając z tych samych strategii, co wbudowany w jądro sterownik LMK (to znaczy 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 konkretnego urządzenia, korzystając z poniższych właściwości.

Nieruchomość Używać Domyślny
ro.config.low_ram Określ, czy urządzenie ma małą ilość pamięci RAM, czy 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żyj progów wolnej pamięci i pamięci podręcznej plików do podejmowania decyzji o zakończeniu procesu (to znaczy dopasuj funkcjonalność wbudowanego sterownika LMK). false
ro.lmk.low Minimalny wynik oom_adj dla procesów, które mogą zostać zabite przy niskim poziomie vmpressure . 1001
(wyłączony)
ro.lmk.medium Minimalny wynik oom_adj dla procesów, które można zabić przy średnim poziomie vmpressure . 800
(usługi buforowane lub nieistotne)
ro.lmk.critical Minimalny wynik oom_adj dla procesów, które mogą zostać zakończone przy krytycznym poziomie vmpressure . 0
(dowolny proces)
ro.lmk.critical_upgrade Włącz aktualizację do poziomu krytycznego. false
ro.lmk.upgrade_pressure Maksymalne mem_pressure , przy którym poziom jest aktualizowany, ponieważ system za dużo podmienia. 100
(wyłączony)
ro.lmk.downgrade_pressure Minimalne mem_pressure , przy którym zdarzenie vmpressure jest ignorowane, ponieważ jest jeszcze dostępna 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 ciśnienia pamięci wprowadzony w Androidzie 10. lmkd w Androidzie 11 uwzględnia poziomy wykorzystania zasobów pamięci i wyrzucanie, aby zapobiec głodowi pamięci i spadkowi wydajności. Ta strategia zabijania zastępuje poprzednie strategie i można jej używać zarówno na urządzeniach o wysokiej wydajności, jak i urządzeniach z małą 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 poprawki PSI i włącz PSI (backporty dostępne w popularnych jądrach Androida 4.9, 4.14 i 4.19).
  • Dołącz poprawki obsługi PIDFD (backporty dostępne we wspólnych 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 następującymi ustawieniami konfiguracyjnymi:

CONFIG_PSI=y

Konfigurowanie lmkd w Androidzie 11

Strategia zabijania pamięci w systemie Android 11 obsługuje pokrętła strojenia i ustawienia domyślne wymienione poniżej. Funkcje te działają zarówno na urządzeniach o wysokiej wydajności, jak i na urządzeniach z małą ilością pamięci RAM.

Nieruchomość Używać Domyślny
Wysoka wydajność Niska pamięć RAM
ro.lmk.psi_partial_stall_ms Próg częściowego przeciągnięcia PSI w milisekundach wyzwalający powiadomienie o braku pamięci. Jeśli urządzenie zbyt późno otrzymuje powiadomienia o zużyciu pamięci, zmniejsz tę wartość, aby uruchomić wcześniejsze powiadomienia. Jeśli niepotrzebnie uruchamiają się powiadomienia o zużyciu pamięci, zwiększ tę wartość, aby urządzenie było mniej wrażliwe na szumy. 70 200
ro.lmk.psi_complete_stall_ms Pełny próg przeciągnięcia PSI w milisekundach wyzwalający powiadomienia o pamięci krytycznej. Jeśli urządzenie zbyt późno otrzyma powiadomienia o krytycznym zużyciu pamięci, zmniejsz tę wartość, aby uruchomić wcześniejsze powiadomienia. Jeśli niepotrzebnie uruchomią się powiadomienia o krytycznym zużyciu pamięci, zwiększ tę wartość, aby urządzenie było mniej wrażliwe na hałas. 700
ro.lmk.thrashing_limit Maksymalna liczba ponownych ustawień zestawu roboczego jako procent całkowitego rozmiaru pamięci podręcznej pliku. Błędy zestawu roboczego powyżej tej wartości oznaczają, że uznaje się, że system niszczy pamięć podręczną stronicowania. Jeżeli wykorzystanie pamięci ma wpływ na wydajność urządzenia, zmniejsz wartość, aby ograniczyć zakłócenia. Jeśli wydajność urządzenia niepotrzebnie spada z powodu szarpania, zwiększ wartość, aby umożliwić większe szarpanie. 100 30
ro.lmk.thrashing_limit_decay Spadek progu drgań wyrażony jako procent pierwotnego progu używanego do obniżenia progu, gdy system nie może się zregenerować, nawet po zabiciu. Jeśli ciągłe bicie powoduje niepotrzebne zabójstwa, zmniejsz wartość. Jeśli reakcja na ciągłe bicie po zabiciu jest zbyt wolna, zwiększ wartość. 10 50
ro.lmk.swap_util_max Maksymalna ilość wymienianej pamięci jako procent całkowitej pamięci wymienialnej. Kiedy ilość wymienianej pamięci przekroczy ten limit, oznacza to, że system zamienił większość swojej pamięci wymiennej i nadal znajduje się pod presją. Może się to zdarzyć, gdy alokacje niewymienne generują obciążenie pamięci, którego nie można zmniejszyć poprzez zamianę, ponieważ większość pamięci wymiennej została już wymieniona. Wartość domyślna to 100, co skutecznie wyłącza tę kontrolę. Jeśli zużycie pamięci ma wpływ na wydajność urządzenia, gdy wykorzystanie wymiany jest wysokie, a poziom darmowej 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ść Używać Domyślny
Wysoka wydajność Niska pamięć RAM
ro.lmk.swap_free_low_percentage Poziom darmowej wymiany jako procent całkowitej przestrzeni wymiany. `lmkd` używa tej wartości jako progu, kiedy należy uznać system za pozbawiony przestrzeni wymiany. Jeśli `lmkd` zabije, gdy w zamian jest za dużo miejsca, zmniejsz wartość procentową. Jeśli zabójstwa `lmkd` zdarzają się zbyt późno, pozwalając na zabójstwa OOM, zwiększ wartość procentową. 20 10
ro.lmk.debug Włącza to dzienniki debugowania `lmkd`. Włącz debugowanie podczas strojenia. false