Speicherplatz in Spielen effizient verwalten

Auf der Android-Plattform versucht das System, so viel Systemspeicher (RAM) wie möglich zu verwenden, und führt verschiedene Speicheroptimierungen durch, um bei Bedarf Speicherplatz freizugeben. Diese Optimierungen können sich negativ auf dein Spiel auswirken, indem sie es verlangsamen oder ganz beenden. Weitere Informationen zu diesen Optimierungen findest du im Hilfeartikel Arbeitsspeicherzuweisung an Prozesse.

Um die Gerätestabilität zu gewährleisten, werden ab Android 17 (API-Level 37) die Arbeitsspeicherlimits für Apps basierend auf dem gesamten RAM des Geräts durchgesetzt. Wenn eine App diese Limits überschreitet, beendet Android den Prozess ohne zugehörigen Stacktrace.

Auf dieser Seite werden die Schritte erläutert, die du unternehmen kannst, um zu verhindern, dass dein Spiel von Problemen mit zu wenig Arbeitsspeicher betroffen ist.

Auf onTrimMemory() reagieren

Das System verwendet onTrimMemory() , um deine App über Lebenszyklusereignisse zu informieren, die eine gute Gelegenheit für deine App darstellen, die Arbeitsspeichernutzung freiwillig zu reduzieren und zu vermeiden, dass sie vom Low-Memory Killer (LMK) beendet wird, um Arbeitsspeicher für andere Apps freizugeben.

Wenn deine App im Hintergrund beendet wird, wird der nächste Start der App für den Nutzer langsam sein Kaltstart. Bei Apps, die ihre Arbeitsspeichernutzung reduzieren, wenn sie in den Hintergrund verschoben werden, ist es weniger wahrscheinlich, dass sie im Hintergrund beendet werden.

Wenn du auf Trim-Ereignisse reagierst, solltest du große Arbeitsspeicherzuweisungen freigeben, die nicht sofort benötigt werden und bei Bedarf neu erstellt werden können. Wenn deine App beispielsweise einen Cache mit Bitmaps enthält, die aus lokal gespeicherten komprimierten Bildern decodiert wurden, ist es oft eine gute Idee, diesen Cache als Reaktion auf TRIM_MEMORY_UI_HIDDEN zu verkleinern oder zu leeren.

Kotlin

class MainActivity : AppCompatActivity(), ComponentCallbacks2 {
    override fun onTrimMemory(level: Int) {
        if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            // Release memory related to UI elements, such as bitmap caches.
        }
        if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
            // Release memory related to background processing, such as by
            // closing a database connection.
        }
    }
}

Java

public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
    public void onTrimMemory(int level) {
        switch (level) {
            if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
                // Release memory related to UI elements, such as bitmap caches.
            }
            if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
                // Release memory related to background processing, such as by
                // closing a database connection.
            }
        }
    }
}

Arbeitsspeicherbudgets konservativ festlegen

Plane den Arbeitsspeicher konservativ, um zu vermeiden, dass der Arbeitsspeicher knapp wird. Hier einige Punkte, die du berücksichtigen solltest:

  • Größe des physischen RAM: Spiele verwenden oft zwischen ¼ und ½ des physischen RAM auf dem Gerät.
  • Maximale zRAM-Größe: Mehr zRAM bedeutet, dass dem Spiel potenziell mehr Arbeitsspeicher zugewiesen werden kann. Dieser Wert kann je nach Gerät variieren. Suche in /proc/meminfo nach SwapTotal, um ihn zu finden.
  • Arbeitsspeichernutzung des Betriebssystems: Bei Geräten, die mehr RAM für System prozesse reservieren, bleibt weniger Arbeitsspeicher für dein Spiel übrig. Das System beendet den Prozess deines Spiels, bevor es Systemprozesse beendet.
  • Arbeitsspeichernutzung installierter Apps: Teste dein Spiel auf Geräten, auf denen viele Apps installiert sind. Social-Media- und Chat-Apps müssen ständig ausgeführt werden und wirken sich auf die Menge des kostenlosen Arbeitsspeichers aus.

Wenn du kein konservatives Arbeitsspeicherbudget festlegen kannst, wähle einen flexibleren Ansatz. Wenn das System Probleme mit zu wenig Arbeitsspeicher hat, reduziere die Menge an Arbeitsspeicher, die das Spiel verwendet. Weise beispielsweise als Reaktion auf onTrimMemory() Texturen mit niedrigerer Auflösung zu oder speichere weniger Shader. Dieser dynamische Ansatz für die Arbeitsspeicherzuweisung erfordert mehr Arbeit vom Entwickler, insbesondere in der Game-Design-Phase.

Seitenflattern vermeiden

Seitenflattern tritt auf, wenn der kostenlose Arbeitsspeicher knapp ist, aber nicht so knapp, dass das Spiel beendet wird. In dieser Situation hat kswapd Seiten freigegeben, die das Spiel noch benötigt. Daher versucht es, die Seiten aus dem Arbeitsspeicher neu zu laden. Es ist nicht genügend Speicherplatz vorhanden, sodass die Seiten immer wieder ausgelagert werden (kontinuierliches Auslagern). Systemtrace-Funktion meldet diese Situation als Thread in dem kswapd kontinuierlich ausgeführt wird.

Ein Symptom von Seitenflattern sind lange Frame-Zeiten, möglicherweise eine Sekunde oder mehr. Reduziere den Speicherbedarf des Spiels, um dieses Problem zu beheben.

Verfügbare Tools verwenden

Android bietet eine Reihe von Tools, mit denen du nachvollziehen kannst, wie das System den Arbeitsspeicher verwaltet.

Meminfo

Dieses Tool erfasst Arbeitsspeicherstatistiken, um zu zeigen, wie viel PSS-Arbeitsspeicher zugewiesen wurde und für welche Kategorien er verwendet wurde.

So kannst du die Meminfo-Statistiken auf eine der folgenden Arten ausgeben:

  • Verwende den Befehl adb shell dumpsys meminfo package-name.
  • Verwende den MemoryInfo Aufruf aus der Android Debug API.

Die PrivateDirty Statistik zeigt die Menge an RAM im Prozess, die nicht auf die Festplatte ausgelagert werden kann und nicht für andere Prozesse freigegeben ist. Der Großteil dieser Menge wird dem System zur Verfügung gestellt, wenn dieser Prozess beendet wird.

Arbeitsspeicher-Tracepoints

Arbeitsspeicher-Tracepoints verfolgen die Menge an RSS-Arbeitsspeicher , die dein Spiel verwendet. Die Berechnung der RSS-Arbeitsspeichernutzung ist viel schneller als die Berechnung der PSS-Nutzung. Da die Berechnung schneller ist, zeigt RSS feinere Abstufungen bei Änderungen der Arbeitsspeichergröße für genauere Messungen der maximalen Arbeitsspeichernutzung. Daher ist es einfacher, Spitzen zu erkennen, die dazu führen könnten, dass der Arbeitsspeicher des Spiels knapp wird.

Perfetto und lange Traces

Perfetto ist eine Suite von Tools zum Erfassen von Leistungs- und Arbeitsspeicherinformationen auf einem Gerät und zum Anzeigen in einer webbasierten Benutzeroberfläche. Es unterstützt beliebig lange Traces, sodass du sehen kannst, wie sich der RSS-Wert im Laufe der Zeit ändert. Du kannst auch SQL-Abfragen für die erzeugten Daten zur Offlineverarbeitung ausführen. Aktiviere lange Traces in der Systemtrace-App. Achte darauf, dass die memory:Memory Kategorie für den Trace aktiviert ist. Für die benutzerdefinierte Arbeitsspeicherinstrumentierung in der Entwicklung und beim Testen kannst du auch die (Beta)heapprofd API verwenden.

heapprofd

heapprofd ist ein Tool zur Arbeitsspeicherverfolgung, das Teil von Perfetto ist. Mit diesem Tool kannst du Arbeitsspeicherlecks finden, indem du siehst, wo Arbeitsspeicher mit malloc zugewiesen wurde. heapprofd kann mit einem Python-Skript gestartet werden. Da das Tool nur geringen Overhead verursacht, wirkt es sich nicht so stark auf die Leistung aus wie andere Tools wie Malloc Debug.

bugreport

bugreport ist ein Logging-Tool, mit dem du herausfinden kannst, ob dein Spiel aufgrund von zu wenig Arbeitsspeicher abgestürzt ist. Die Ausgabe des Tools ist viel detaillierter als bei der Verwendung von logcat. Es ist nützlich für das Debugging von Arbeitsspeicherproblemen, da es zeigt, ob dein Spiel aufgrund von zu wenig Arbeitsspeicher abgestürzt ist oder vom LMK beendet wurde.

Weitere Informationen findest du unter Fehlerberichte erfassen und lesen.