Wykorzystanie pamięci przez bitmapę

Bitmapy są często największymi obiektami zużywającymi pamięć w aplikacji. Operacje dekodowania i skalowania często znajdują się na ścieżce krytycznej renderowania klatek. Optymalizacja wykorzystania pamięci przez bitmapy znacznie poprawia szybkość reakcji interfejsu, żywotność baterii i ogólną stabilność, ponieważ zmniejsza liczbę zacięć, błędów ANR i przypadków zakończenia procesu z powodu braku pamięci.

Identyfikowanie wysokiego wykorzystania pamięci przez bitmapy

Android Vitals podaje dane o wykorzystaniu pamięci przez bitmapy w aplikacji, agregując dane z urządzeń z Androidem. Te dane obejmują percentyle oparte na okresach (np. 28-dniowych) dla każdego pakietu i procesu. Te dane pomagają identyfikować trendy i potencjalne regresje w zakresie wydajności pamięci na różnych typach i wersjach urządzeń.

Android Vitals udostępnia informacje o wykorzystaniu pamięci przez bitmapy w aplikacji podzielone według tych stanów procesu:

  • Pierwszy plan: proces aplikacji jest widoczny. Oczekuje się, że wartość P99 będzie znacznie wyższa na pierwszym planie niż w innych stanach procesu, ale deweloperzy powinni sprawdzić, czy stosunek P99 do P50 jest znaczący (np. wyższy niż 3,5), ponieważ często wskazuje to na wyciek pamięci bitmapy. Możesz to sprawdzić, szukając rozbieżności między typowym wykorzystaniem (P50) a wykorzystaniem odstającym (P99). Ogólne nadmierne wykorzystanie zasobów powoduje równomierne zwiększenie wykorzystania pamięci we wszystkich percentylach, ale wycieki pamięci z czasem się kumulują, co powoduje znaczne odchylenie danych na końcu ogona (P99). Upewnij się, że alokacje bitmap na pierwszym planie nie są niepotrzebnie utrzymywane po przejściu aplikacji do innych stanów.
  • Usługi widoczne dla użytkownika: proces aplikacji działa w stanie widocznym. Obejmuje to usługi na pierwszym planie, przyspieszone zadania i dane inicjowane przez użytkownika przesyłania danych. Aplikacje nie mogą utrzymywać dużych alokacji bitmap na pierwszym planie podczas przechodzenia do tych stanów. Ponieważ te usługi są przeznaczone do długotrwałych zadań, utrzymywanie dużych zasobów pogarsza ogólne wrażenia użytkownika i zmusza demon Low Memory Killer (LMKD) do odzyskiwania pamięci przez zamykanie procesów o niższym priorytecie.
  • Tło: aplikacja uruchamia usługę w tle lub niedawno przeszła do tła, ale nie jest jeszcze buforowana. Ponieważ ten stan procesu jest mniej ważny niż procesy na pierwszym planie lub widoczne, aplikacje powinny w tym przypadku jawnie zwalniać duże zasoby bitmap, aby zmniejszyć obciążenie pamięci.
  • Buforowane: aplikacja jest w stanie buforowanym. Ten stan jest bardzo wrażliwy na obciążenie pamięci systemowej, np. na błędy LMK. Aplikacje muszą aktywnie zmniejszać wykorzystanie pamięci przez bitmapy w tym stanie, aby uniknąć usunięcia przez system operacyjny.

Czynniki przyczyniające się do wysokiego wykorzystania pamięci przez bitmapy

W obliczeniach może być też uwzględniona pamięć wirtualna, która nigdy nie była używana. Jeśli zauważysz nieoczekiwanie wysokie wykorzystanie pamięci przez bitmapy, sprawdź, czy nie przydzielasz pamięci, która nie jest używana.

Zasoby

Analizowanie bitmap w Android Studio

Profilowanie bitmap w Android Studio

Użyj narzędzia Memory Profiler, aby w czasie rzeczywistym sprawdzać alokacje pamięci, przechwytywać zrzuty sterty i analizować obiekty pod kątem wycieków pamięci. Dodatkowo użyj analizatora sterty, aby wykrywać wycieki pamięci, identyfikować zduplikowane alokacje bitmap i wizualizować utrzymywanie obiektów.

Automatyczne wykrywanie wycieków za pomocą biblioteki LeakCanary

Zintegruj bibliotekę LeakCanary, aby zautomatyzować wykrywanie wycieków pamięci w aplikacji. Biblioteka LeakCanary zapewnia automatyczną analizę sterty, identyfikując obiekty, które powinny zostać usunięte przez odśmiecanie pamięci, ale nadal są przechowywane w pamięci, np. bitmapy zachowane przez zniszczone aktywności lub fragmenty.

Dokumentacja dotycząca wydajności bitmap

Te zasoby zawierają wyczerpujące wskazówki dotyczące sprawdzonych metod wydajnego obsługiwania bitmap w różnych komponentach Androida.

Lista kontrolna dla deweloperów dotycząca optymalizacji wykorzystania pamięci przez bitmapy

Aby zoptymalizować wydajność pamięci bitmapy, postępuj zgodnie z 3 podstawowymi zasadami: ograniczaj, używaj ponownie i zwalniaj.

  • Ograniczaj: minimalizuj początkowe wykorzystanie pamięci podczas wczytywania lub wyświetlania bitmap.
  • Używaj ponownie: wdrażaj mechanizmy buforowania, aby uniknąć zbędnych alokacji bitmap.
  • Zwalniaj: aktywnie zwalniaj zasoby, aby umożliwić ponowne przydzielenie pamięci na potrzeby aktywnych procesów.

Ta lista kontrolna dla deweloperów może pomóc Ci zoptymalizować wykorzystanie pamięci przez bitmapy.

Podstawowa zasada Obszar Opis
Ograniczaj Eliminowanie zduplikowanych bitmap Analizuj zrzuty sterty za pomocą narzędzia Memory Profiler, aby wykrywać zbędne alokacje bitmap. Zapoznaj się z przewodnikiem Zarządzanie pamięcią bitmapy.
Korzystanie z bibliotek wczytywania obrazów Używaj bibliotek takich jak Glide i Coil, aby zautomatyzować obsługę wątków, buforowanie i wydajne dekodowanie.
Wdrażanie próbkowania w dół Dekoduj obrazy tak, aby pasowały do wymiarów docelowego kontenera interfejsu, zamiast wczytywać zasoby w pełnej rozdzielczości.
Używanie formatu RGB_565 w przypadku obrazów nieprzezroczystych Zmniejsz wykorzystanie pamięci o 50%, przechodząc z formatu ARGB_8888 na konfigurację 16-bitową w przypadku obrazów bez przezroczystości.
Nadawanie priorytetu elementom VectorDrawable Używaj wektorów w przypadku ikon i podstawowych grafik, aby zapewnić ostre skalowanie przy minimalnym obciążeniu pamięci.
Optymalizowanie dostarczania obrazów po stronie serwera Skonfiguruj interfejsy API backendu tak, aby udostępniały obrazy dostosowane do gęstości urządzenia i wymiarów elementu ImageView.
Eliminowanie przezroczystych marginesów Unikaj przydzielania pamięci na „niewidoczne” piksele, używając elementu InsetDrawable lub dopełnienia układu zamiast wbudowanych marginesów. Zapoznaj się z artykułem Tworzenie aplikacji na Androida o wysokiej wydajności pamięci.
Używaj ponownie Konfigurowanie optymalnych rozmiarów pamięci podręcznej Dostosuj limity pamięci i pamięci podręcznej dysku na podstawie pamięci RAM urządzenia i rozdzielczości ekranu. Zapoznaj się z artykułem Buforowanie bitmap.
Zwalniaj Czyszczenie zasobów w tle Wdróż TRIM_MEMORY_BACKGROUND, aby wyczyścić pamięć podręczną i poprawić przetrwanie procesu podczas obciążenia pamięci systemowej.
Zwalnianie zasobów, gdy interfejs jest ukryty Użyj TRIM_MEMORY_UI_HIDDEN, aby zwolnić pamięć podręczną bitmap, gdy aplikacja nie jest już widoczna dla użytkownika.
Monitorowanie wycieków pamięci Użyj biblioteki LeakCanary i narzędzia Memory Profiler, aby znaleźć bitmapy zachowane po zniszczeniu ich elementu LifecycleOwner. Zapoznaj się z artykułem Zarządzanie pamięcią aplikacji.