Na platformie Androida system stara się wykorzystać jak najwięcej pamięci RAM i w razie potrzeby wykonuje różne optymalizacje pamięci, aby zwolnić miejsce. Te optymalizacje mogą mieć negatywny wpływ na grę – spowolnienie jej działania lub jej całkowite wyłączenie. Więcej informacji o tych optymalizacji znajdziesz w temacie Alokacja pamięci między procesy.
Na tej stronie opisujemy, jak uniknąć problemów z brakiem pamięci, które wpływa na grę.
Odpowiedź na onTrimMemory()
System używa parametru onTrimMemory()
, aby powiadomić aplikację, że kończy się pamięć i aplikacja może zostać zatrzymana. W wielu przypadkach jest to jedyne ostrzeżenie, które aplikacja dostaje. Wywołanie zwrotne ma wysoki czas oczekiwania w porównaniu z meczem o małej ilości pamięci (LMK), dlatego tak ważne jest szybkie reagowanie na to wywołanie.
W odpowiedzi na to wywołanie zwrotne zmniejsz szybkość, liczbę i rozmiar przydziałów.
onTrimMemory()
przekazuje stałą wskazującą wagę, ale odpowiadaj na pierwsze ostrzeżenie, ponieważ możliwe jest przydzielanie szybciej, niż może zareagować onTrimMemory()
.
Kotlin
class MainActivity : AppCompatActivity(), ComponentCallbacks2 { override fun onTrimMemory(level: Int) { when (level) { ComponentCallbacks2.TRIM_MEMORY_MODERATE, ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW, ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> // Respond to low memory condition else -> Unit } } }
Java
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 { public void onTrimMemory(int level) { switch (level) { case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: // Respond to low memory condition break; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: // Respond to low memory condition break; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: // Respond to low memory condition break; default: break;
C#
using UnityEngine; using System.Collections; using System.Collections.Generic; class LowMemoryTrigger : MonoBehaviour { private void Start() { Application.lowMemory += OnLowMemory; } private void OnLowMemory() { // Respond to low memory condition (e.g., Resources.UnloadUnusedAssets()) } }
Korzystanie z interfejsu Memory Advice API w wersji beta
Interfejs Memory Advice API został stworzony jako alternatywa dla onTrimMemory, który zapewnia znacznie większą czułość i precyzję w przewidywaniu nadchodzących zespołów LMK. Aby to osiągnąć, interfejs API szacuje ilość używanych zasobów pamięci, a potem powiadamia aplikację o przekroczeniu określonych wartości progowych. Interfejs API może też raportować szacowany odsetek wykorzystania pamięci bezpośrednio w aplikacji. Interfejs Memory Advice API może być alternatywą dla zdarzeń onTrimMemory
do zarządzania pamięcią.
Aby korzystać z interfejsu Memory Advice API, zapoznaj się z przewodnikiem dla początkujących.
Stosuj rozsądne budżety na pamięć
Ograniczaj ilość pamięci, aby uniknąć wyczerpania pamięci. Oto kilka kwestii, które warto wziąć pod uwagę:
- Rozmiar fizycznej pamięci RAM: gry wykorzystują często od 1⁄4 do 1⁄2 ilości fizycznej pamięci RAM na urządzeniu.
- Maksymalny rozmiar pamięci RAMRAM: więcej pamięci RAMRAM oznacza, że gra może mieć więcej pamięci do przydzielenia. Ta wartość może się różnić w zależności od urządzenia. Aby ją znaleźć, poszukaj fragmentu
SwapTotal
w polu/proc/meminfo
. - Wykorzystanie pamięci systemu operacyjnego: urządzenia, które wyznaczają więcej pamięci RAM procesom systemowym, pozostawiają mniej pamięci dla gry. System zamyka procesy gry, zanim zniszczy procesy systemowe.
- Wykorzystanie pamięci przez zainstalowane aplikacje: możesz przetestować grę na urządzeniach z zainstalowanymi aplikacjami. Aplikacje do mediów społecznościowych i czatu muszą stale działać i określać ilość wolnej pamięci.
Jeśli nie możesz wybrać takiego budżetu, przyjmij bardziej elastyczne podejście. Jeśli w systemie występują problemy z małą ilością pamięci, zmniejsz ilość pamięci używanej przez grę. Na przykład przydziel tekstury o niższej rozdzielczości lub przechowuj mniej cieniowania w odpowiedzi na żądanie onTrimMemory()
. Takie dynamiczne podejście do alokacji pamięci wymaga od dewelopera więcej pracy, zwłaszcza na etapie projektowania gry.
Unikaj szarpania
Trzęsienie ma miejsce, gdy ilość wolnej pamięci jest niska, ale jest ona niewystarczająca, aby zakończyć działanie gry.
W tej sytuacji kswapd
odzyskał(a) strony, których gra nadal potrzebuje, więc próbuje ponownie załadować je z pamięci. Za mało miejsca, więc strony
są zastępowane (ciągła zamiana).
Śledzenie systemu zgłasza tę sytuację jako wątek, w którym kswapd
działa w sposób ciągły.
Jednym z objawów ubijania jest długi czas renderowania klatki, który czasem trwa co najmniej sekundę. Aby rozwiązać ten problem, zmniejsz rozmiar pamięci gry.
Korzystanie z dostępnych narzędzi
Android ma zbiór narzędzi, które pomagają zrozumieć, jak system zarządza pamięcią.
Informacje o pamięci
To narzędzie gromadzi statystyki dotyczące pamięci, aby pokazać, ile pamięci PSS zostało przydzielone oraz kategorie, w przypadku których była używana.
Statystyki meminfo możesz wydrukować na jeden z tych sposobów:
- Użyj polecenia
adb shell dumpsys meminfo package-name
. - użyj wywołania
MemoryInfo
z interfejsu Android Debug API.
Statystyka PrivateDirty
pokazuje ilość pamięci RAM w procesie, której nie można stronicować na dysk i której nie można udostępnić innym procesom. Większość tej ilości staje się dostępna dla systemu po
zakończeniu tego procesu.
Punkty śledzenia pamięci
Punkty śledzenia pamięci śledzą ilość pamięci RSS używanej przez grę. Obliczanie wykorzystania pamięci RSS jest znacznie szybsze niż obliczanie wykorzystania PSS. Ponieważ obliczenia są szybsze, RSS pokazuje bardziej szczegółowe informacje o zmianach rozmiaru pamięci, co pozwala dokładniej mierzyć szczytowe wykorzystanie pamięci. Dzięki temu łatwiej jest dostrzec szczyty, które mogą powodować za mało pamięci w grze.
Perfetto i długie ślady
Perfetto to zestaw narzędzi do gromadzenia informacji o wydajności i pamięci urządzenia oraz do wyświetlania ich w internetowym interfejsie użytkownika. Obsługuje dowolnie długie ślady, dzięki czemu możesz obserwować, jak kanał RSS zmienia się w czasie. Możesz też wysyłać zapytania SQL do danych na potrzeby przetwarzania offline. Włącz długie logi czasu w aplikacji Śledzenie systemu. Sprawdź, czy dla logu czasu włączona jest kategoria memory:Memory.
Heapprofd
heapprofd
to narzędzie do śledzenia pamięci, które jest częścią Perfetto. To narzędzie może pomóc Ci znaleźć wycieki pamięci, pokazując, gdzie pamięć została przydzielona za pomocą malloc
. heapprofd
można zacząć przy użyciu skryptu Pythona, a ponieważ narzędzie jest mało wydajne, nie wpływa na wydajność tak jak inne narzędzia, takie jak Malloc Debug.
zgłoszenie błędów
bugreport
to narzędzie do logowania, które pozwala sprawdzić, czy gra uległa awarii z powodu wyczerpania pamięci. Dane wyjściowe narzędzia są znacznie bardziej szczegółowe niż dane uzyskane za pomocą narzędzia logcat. Jest przydatny przy debugowaniu pamięci, bo pokazuje, czy gra uległa awarii z powodu wyczerpania pamięci lub jeśli została przerwana przez LMK.
Więcej informacji znajdziesz w artykule Rejestrowanie i odczytywanie raportów o błędach.