Przydział pamięci między procesy

Platforma Android działa zgodnie z założeniami, że wolna pamięć to marnowana pamięć. Próbuje użyć całej dostępnej pamięci przez cały czas. Na przykład system zapisuje aplikacje w pamięci po ich zamknięciu, aby użytkownik mógł szybko do nich wrócić. Z tego powodu urządzenia z Androidem często mają bardzo mało wolnej pamięci. Zarządzanie pamięcią jest niezbędne do odpowiedniego przydzielania pamięci między ważne procesy systemowe i wiele aplikacji użytkowników.

Na tej stronie omawiamy podstawowe informacje o tym, jak Android przydziela pamięć na potrzeby systemu i aplikacji użytkowników. Wyjaśnia także, jak system operacyjny reaguje na sytuacje związane z małą ilością pamięci.

Typy pamięci

Urządzenia z Androidem mają 3 różne typy pamięci: RAM, zRAM i miejsce na dane. Pamiętaj, że zarówno CPU, jak i GPU mają dostęp do tej samej pamięci RAM.

Typy pamięci

Rysunek 1. Typy pamięci – RAM, zRAM i miejsce na dane.

  • Pamięć RAM jest najszybszym typem pamięci, ale zwykle ma niewielki rozmiar. Urządzenia zaawansowane zwykle mają najwięcej pamięci RAM.

  • zRAM to partycja pamięci RAM używana na potrzeby przestrzeni wymiany. Wszystko jest kompresowane po umieszczeniu w zRAM, a następnie dekompresowane po skopiowaniu z pamięci zRAM. Ta część pamięci RAM zwiększa lub zmniejsza się w miarę przenoszenia stron do zRAM lub ich usuwania. Producenci urządzeń mogą ustawić maksymalny rozmiar.

  • Pamięć ma wszystkie trwałe dane, takie jak system plików i dołączony kod obiektu do wszystkich aplikacji, bibliotek i platformy. Pamięć ma znacznie większą pojemność niż pozostałe 2 rodzaje pamięci. Na Androidzie miejsce na dane nie jest używane do wymiany, tak jak w innych implementacjach systemu Linux, ponieważ częste pisanie może powodować zużycie pamięci i skrócić żywotność nośnika pamięci.

Strony pamięci

Pamięć RAM jest podzielona na strony. Zwykle każda strona ma 4 KB pamięci.

Strony są uznawane za bezpłatne lub używane. Bezpłatne strony to niewykorzystana pamięć RAM. Używane strony to pamięć RAM, z której system aktywnie korzysta. Są one podzielone na te kategorie:

  • Pamięć podręczna: pamięć obsługiwana przez plik zapisany w pamięci (np. kod lub pliki mapowane na pamięć). Istnieją 2 typy pamięci podręcznej:
    • Prywatne: należą do jednego procesu i nie są udostępnione.
      • Oczyszczona: niezmodyfikowana kopia pliku zapisanego w pamięci; można ją usunąć do kswapd, aby zwiększyć ilość wolnej pamięci
      • Niepotrzebna: zmodyfikowana kopia pliku na dysku; można ją przenieść do zRAM lub skompresować do niej za pomocą kswapd, aby zwiększyć ilość wolnej pamięci.
    • Udostępnione: używane przez wiele procesów.
      • Oczyszczona: niezmodyfikowana kopia pliku na dysku; można ją usunąć do kswapd, aby zwiększyć ilość wolnej pamięci
      • Niepotrzebna: zmodyfikowana kopia pliku na dysku; umożliwia zapisywanie zmian z powrotem do pliku w pamięci w celu zwiększenia ilości wolnej pamięci przez kswapd lub jawne użycie metody msync() lub munmap()
  • Anonimowa: pamięć nie jest wspierana przez plik w pamięci (na przykład jest przydzielona przez mmap() z ustawioną flagą MAP_ANONYMOUS)
    • Zabrudzony: można go przenieść/skompresować w zRAM do kswapd, aby zwiększyć ilość wolnej pamięci.

Proporcje bezpłatnych i używanych stron zmieniają się z upływem czasu, ponieważ system aktywnie zarządza pamięcią RAM. Pojęcia przedstawione w tej sekcji są kluczowe w zarządzaniu sytuacjami z małą ilością pamięci. W następnej sekcji tego dokumentu znajdziesz więcej informacji na ten temat.

Zarządzanie mało pamięcią

Android ma 2 główne mechanizmy radzenia sobie z małą ilością pamięci: demon wymiany jądra i mechanizm zagrożenia małej ilości pamięci.

demon wymiany jądra

Demon wymiany jądra (kswapd) jest częścią jądra systemu Linux i konwertuje używaną pamięć w wolną pamięć. Demon uruchamia się, gdy na urządzeniu kończy się wolne miejsce. Jądro systemu Linux utrzymuje niskie i wysokie progi wolnej pamięci. Gdy wolna pamięć spadnie poniżej dolnego progu, kswapd rozpoczyna odzyskiwanie pamięci. Gdy wolna pamięć osiągnie górny próg, kswapd przestanie ją odzyskiwać.

kswapd może odzyskać wyczyszczone strony, usuwając je, ponieważ mają miejsce na dane i nie zostały zmodyfikowane. Jeśli proces próbuje naprawić usuniętą stronę, system skopiuje ją z pamięci RAM. Ta operacja jest nazywana stronicowaniem na żądanie.

Wyczyszczona strona wykorzystująca miejsce na dane została usunięta

Rysunek 2. Wyczyszczona strona (zawierająca miejsce na dane) została usunięta

kswapd może przenieść prywatne, zanieczyszczone strony zapisane w pamięci podręcznej i anonimowe brudne strony do zRAM, gdzie są one skompresowane. W ten sposób zwolnisz ilość dostępnej pamięci RAM (wolne strony). Jeśli proces spróbuje dotknąć zanieczyszczonej strony w zRAM, strona zostanie zdekompresowana i z powrotem do pamięci RAM. Jeśli proces powiązany ze skompresowaną stroną zostanie przerwany, zostanie ona usunięta z zRAM.

Jeśli ilość wolnej pamięci spadnie poniżej określonego progu, system rozpocznie zamykanie procesów.

Brudna strona została przeniesiona do zRAM i skompresowana

Rysunek 3. Brudna strona została przeniesiona do zRAM i skompresowana

Zabójca, który ma mało pamięci

kswapd często nie może zwolnić wystarczającej ilości pamięci dla systemu. W takim przypadku system używa metody onTrimMemory(), aby powiadamiać aplikację o wyczerpywaniu się pamięci i konieczności ograniczenia jej przydziałów. Jeśli to nie wystarcza, jądro zaczyna zamykać procesy, aby zwolnić pamięć. Wykorzystuje do tego celu narzędzie o małej ilości pamięci (LKM-killer).

Aby zdecydować, który proces zakończyć, LMK wykorzystuje wynik „brak pamięci” o nazwie oom_adj_score, który określa priorytety uruchomionych procesów. Procesy o wysokim wyniku są przerywane jako pierwsze. Aplikacje w tle zatrzymują się najpierw, a procesy systemowe na końcu. W tabeli poniżej znajdziesz listę kategorii punktacji LMK (od wysokiej do najniższej). Elementy w pierwszej kategorii w pierwszym wierszu zostaną zabite jako pierwsze:

Procesy na Androidzie, najwyższy wynik

Rysunek 4. procesów w Androidzie z wysokimi wynikami u góry i niskimi u dołu

Poniżej znajdziesz opisy różnych kategorii wymienionych w powyższej tabeli:

  • Aplikacje w tle – aplikacje, które wcześniej były uruchomione, a obecnie nie są aktywne. LMK najpierw wyłącza aplikacje w tle, zaczynając od tej o największej wartości oom_adj_score.

  • Poprzednia aplikacja: ostatnio używana aplikacja działająca w tle. Poprzednia aplikacja ma wyższy priorytet (niższy wynik) niż aplikacja działająca w tle, ponieważ z większym prawdopodobieństwem użytkownik przełączy się na nią niż na jedną z aplikacji działających w tle.

  • Aplikacja Google Home: to jest aplikacja uruchamiająca. Po jej wyłączeniu tapeta zniknie.

  • Usługi: usługi są uruchamiane przez aplikacje i mogą obejmować synchronizację lub przesyłanie do chmury.

  • Aplikacje wyczuwalne: aplikacje działające na pierwszym planie, które są w jakiś sposób dostrzegalne dla użytkownika, np. uruchamiające proces wyszukiwania, który wyświetla mały interfejs, lub słuchają muzyki.

  • Aplikacja na pierwszym planie: aplikacja, której aktualnie używasz. Wyłączenie aplikacji na pierwszym planie wygląda jak awaria aplikacji, która może wskazywać użytkownikowi, że coś jest nie tak z urządzeniem.

  • Trwałe (usługi): są to podstawowe usługi urządzenia, np. telefon i Wi-Fi.

  • System: procesy systemowe. Po zakończeniu tych procesów telefon może sprawiać wrażenie, że sam się zrestartuje.

  • Natywna: procesy niskiego poziomu używane przez system (np. kswapd).

Producenci urządzeń mogą zmienić działanie LMK.

Obliczam wykorzystanie pamięci

Jądro śledzi wszystkie strony pamięci znajdujące się w systemie.

Strony używane przez różne procesy

Rysunek 5. Strony używane przez różne procesy

Podczas określania ilości pamięci wykorzystywanej przez aplikację, system musi uwzględniać współdzielone strony. Aplikacje, które mają dostęp do tej samej usługi lub biblioteki, będą współużytkować strony pamięci. Na przykład Usługi Google Play i gra mobilna mogą udostępniać usługę lokalizacyjną. Utrudnia to określenie, ile pamięci należy do danej usługi, a ile pamięci do poszczególnych aplikacji.

Strony udostępniane przez 2 aplikacje

Rysunek 6. Strony udostępniane przez 2 aplikacje (połowa)

Do określenia wykorzystania pamięci przez aplikację można użyć dowolnego z tych wskaźników:

  • Rozmiar zestawu rezydentów (RSS): liczba udostępnianych i nieudostępnianych stron, z których korzysta aplikacja
  • Proporcjonalny rozmiar zestawu (PSS): liczba nieudostępnianych stron używanych przez aplikację i równomierny rozkład udostępnionych stron (np. jeśli 3 procesy współdzielą 3 MB, każdy proces otrzymuje 1 MB w PSS)
  • Unikalny rozmiar zestawu (USS): liczba nieudostępnionych stron używanych przez aplikację (nie obejmuje stron udostępnianych).

Usługa PSS jest przydatna dla systemu operacyjnego, gdy chce sprawdzić ilość pamięci wykorzystywanej przez wszystkie procesy, ponieważ strony nie są zliczane wielokrotnie. Obliczenie PSS zajmuje dużo czasu, ponieważ system musi określić, które strony są udostępniane i przez ile procesów. RSS nie rozróżnia stron udostępnianych i nieudostępnianych (co przyspiesza obliczenia) i lepiej sprawdza się w śledzeniu zmian w alokacji pamięci.

Dodatkowe materiały