Wie erkennt man programmgesteuert die Größe des Anwendungsheaps, die für eine Android-App verfügbar ist?
Ich habe gehört, dass es eine Funktion gibt, die dies in späteren Versionen des SDK tut. Auf jeden Fall suche ich nach einer Lösung, die für 1.5 und höher funktioniert.
android
memory
heap
heap-memory
hpique
quelle
quelle
Antworten:
Es gibt zwei Möglichkeiten, über Ihren Ausdruck "Größe des Anwendungsheaps verfügbar" nachzudenken:
Wie viel Heap kann meine App verwenden, bevor ein schwerer Fehler ausgelöst wird? Und
Wie viel Heap sollte meine App angesichts der Einschränkungen der Android-Betriebssystemversion und der Hardware des Geräts des Benutzers verwenden?
Es gibt eine andere Methode zur Bestimmung der oben genannten.
Für Punkt 1 oben:
maxMemory()
Dies kann
onCreate()
wie folgt aufgerufen werden (z. B. in der Methode Ihrer Hauptaktivität ):Diese Methode gibt an, wie viele Heap- Bytes Ihre App insgesamt verwenden darf .
Für Punkt 2 oben:
getMemoryClass()
die wie folgt aufgerufen werden kann:
Diese Methode gibt ungefähr an, wie viele Megabyte Heap Ihre App verwenden sollte , wenn die Grenzen des aktuellen Geräts und die Rechte anderer Apps zur Ausführung beachtet werden sollen, ohne wiederholt in den
onStop()
/onResume()
-Zyklus gezwungen zu werden, da diese grob sind Der Speicher wird gelöscht, während Ihre Elefanten-App im Android-Whirlpool badet.Diese Unterscheidung ist meines Wissens nicht eindeutig dokumentiert, aber ich habe diese Hypothese auf fünf verschiedenen Android-Geräten getestet (siehe unten) und zu meiner eigenen Zufriedenheit bestätigt, dass dies eine korrekte Interpretation ist.
Bei einer Standardversion von Android
maxMemory()
wird normalerweise ungefähr die gleiche Anzahl von Megabyte zurückgegeben, wie in angegebengetMemoryClass()
(dh ungefähr eine Million Mal der letztere Wert).Die einzige Situation (von der ich weiß), in der die beiden Methoden voneinander abweichen können, ist ein gerootetes Gerät, auf dem eine Android-Version wie CyanogenMod ausgeführt wird. Auf diese Weise kann der Benutzer manuell auswählen, wie groß ein Heap für jede App sein soll. In CM wird diese Option beispielsweise unter "CyanogenMod-Einstellungen" / "Leistung" / "VM-Heap-Größe" angezeigt.
HINWEIS: BEACHTEN SIE, DASS DIE MANUELLE EINSTELLUNG DIESES WERTES IHR SYSTEM MESSEN KANN, INSBESONDERE, wenn Sie einen kleineren Wert als für Ihr Gerät normal auswählen.
Hier sind meine Testergebnisse, die die von
maxMemory()
undgetMemoryClass()
für vier verschiedene Geräte mit CyanogenMod zurückgegebenen Werte zeigen , wobei jeweils zwei verschiedene (manuell eingestellte) Heap-Werte verwendet werden:Darüber hinaus habe ich auf einem Novo7 Paladin-Tablet mit Ice Cream Sandwich getestet. Dies war im Wesentlichen eine Standardversion von ICS, mit der Ausnahme, dass ich das Tablet durch einen einfachen Prozess gerootet habe, der nicht das gesamte Betriebssystem ersetzt und insbesondere keine Schnittstelle bietet, über die die Heap-Größe manuell angepasst werden kann.
Für dieses Gerät sind hier die Ergebnisse:
Auch (per Kishore in einem Kommentar unten):
Und (laut Akauppis Kommentar):
Per Kommentar von cmcromance:
Und (Kommentare von Tencent):
Andere Geräte
Ich habe diese beiden Methoden nicht mit dem speziellen Android getestet: largeHeap = "true" Manifestoption, die seit Honeycomb verfügbar ist, aber dank cmcromance und tencent haben wir einige Beispielwerte für largeHeap, wie oben angegeben.
Meine Erwartung (die durch die oben genannten LargeHeap-Zahlen unterstützt zu werden scheint) wäre, dass diese Option einen ähnlichen Effekt hat wie das manuelle Festlegen des Heaps über ein verwurzeltes Betriebssystem - dh den Wert von erhöht,
maxMemory()
während Sie ingetMemoryClass()
Ruhe lassen. Es gibt eine andere Methode, getLargeMemoryClass (), die angibt, wie viel Speicher für eine App mit der Einstellung largeHeap zulässig ist. In der Dokumentation zu getLargeMemoryClass () heißt es: "Die meisten Anwendungen sollten nicht so viel Speicher benötigen und stattdessen das Limit getMemoryClass () einhalten."Wenn ich richtig geraten habe, hätte die Verwendung dieser Option dieselben Vorteile (und Gefahren) wie die Verwendung des Speicherplatzes, der von einem Benutzer bereitgestellt wird, der den Heap über ein verwurzeltes Betriebssystem erhöht hat (dh wenn Ihre App den zusätzlichen Speicher verwendet). Es wird wahrscheinlich nicht so gut mit allen anderen Apps gespielt, die der Benutzer gleichzeitig ausführt.
Beachten Sie, dass die Speicherklasse anscheinend kein Vielfaches von 8 MB sein muss.
Aus dem
getMemoryClass()
Obigen können wir ersehen, dass das Ergebnis für eine bestimmte Geräte- / Betriebssystemkonfiguration unverändert bleibt, während sich der Wert für maxMemory () ändert, wenn der Heap vom Benutzer anders festgelegt wird.Meine eigene praktische Erfahrung ist, dass ich auf dem G1 (mit einer Speicherklasse von 16), wenn ich manuell 24 MB als Heap-Größe auswähle, ohne Fehler ausgeführt werden kann, selbst wenn meine Speichernutzung auf 20 MB ansteigen darf (vermutlich könnte dies der Fall sein) bis zu 24 MB hoch gehen, obwohl ich das noch nicht ausprobiert habe). Aber andere ähnlich große Apps werden möglicherweise aufgrund der Schweinerei meiner eigenen App aus dem Speicher gelöscht. Umgekehrt wird meine App möglicherweise aus dem Speicher gelöscht, wenn diese anderen wartungsintensiven Apps vom Benutzer in den Vordergrund gerückt werden.
Sie können also nicht die von angegebene Speichermenge überschreiten
maxMemory()
. Und Sie sollten versuchen , innerhalb der von angegebenen Grenzen zu bleibengetMemoryClass()
. Eine Möglichkeit, dies zu tun, besteht darin, die Funktionalität solcher Geräte so einzuschränken, dass Speicherplatz gespart wird, wenn alles andere fehlschlägt.Wenn Sie vorhaben, die in angegebene Anzahl von Megabyte zu überschreiten
getMemoryClass()
, würde ich Ihnen raten, lange und intensiv am Speichern und Wiederherstellen des Status Ihrer App zu arbeiten, damit die Benutzererfahrung praktisch nicht unterbrochen wird, wenn einonStop()
/onResume()
Zyklus auftritt.In meinem Fall beschränke ich meine App aus Leistungsgründen auf Geräte mit 2.2 und höher. Dies bedeutet, dass fast alle Geräte, auf denen meine App ausgeführt wird, eine Speicherklasse von 24 oder höher haben. So kann ich bis zu 20 MB Heap belegen und bin mir ziemlich sicher, dass meine App mit den anderen Apps, die der Benutzer möglicherweise gleichzeitig ausführt, gut funktioniert.
Es wird jedoch immer einige Root-Benutzer geben, die eine Android-Version 2.2 oder höher auf ein älteres Gerät (z. B. ein G1) geladen haben. Wenn Sie eine solche Konfiguration auftreten, im Idealfall sollten Sie Ihre Speichernutzung abspecken, auch wenn
maxMemory()
Ihnen sagt , dass Sie viel höher als die 16MB gehen können , diegetMemoryClass()
Ihnen sagt , dass Sie sollten Targeting werden. Und wenn Sie nicht zuverlässig sicherstellen können, dass Ihre App innerhalb dieses Budgets lebt, stellen Sie zumindest sicher, dassonStop()
/onResume()
nahtlos funktioniert.getMemoryClass()
Wie von Diane Hackborn (hackbod) oben angegeben, ist sie nur ab API-Level 5 (Android 2.0) verfügbar. Sie können daher davon ausgehen, dass die physische Hardware aller Geräte, auf denen eine frühere Version des Betriebssystems ausgeführt wird, ausgelegt ist um Apps optimal zu unterstützen, die einen Heap-Speicherplatz von nicht mehr als 16 MB belegen.Im Gegensatz dazu
maxMemory()
wird gemäß der Dokumentation, die ganzen Weg zurück auf API - Ebene 1 zur Verfügung stehtmaxMemory()
, auf einer Pre-2.0 - Version wird wahrscheinlich gibt einen 16MB Wert, aber ich tue , dass in meinen (viel später) CyanogenMod Versionen der Benutzer Sie können einen Heap-Wert von nur 12 MB auswählen, was vermutlich zu einer niedrigeren Heap-Grenze führen würde. Daher würde ich vorschlagen, dass Sie denmaxMemory()
Wert auch für Versionen des Betriebssystems vor 2.0 weiter testen . In dem unwahrscheinlichen Fall, dass dieser Wert sogar auf weniger als 16 MB festgelegt ist, müssen Sie möglicherweise sogar die Ausführung verweigern, wenn Sie mehr alsmaxMemory()
angegeben benötigen .quelle
Die offizielle API lautet:
quelle
Debug.getNativeHeapSize()
werde den Trick machen, sollte ich denken. Es ist jedoch seit 1.0 da.Die
Debug
Klasse verfügt über viele großartige Methoden zum Verfolgen von Zuordnungen und anderen Leistungsproblemen. Wenn Sie eine Situation mit wenig Arbeitsspeicher feststellen müssen, überprüfen Sie diesActivity.onLowMemory()
.quelle
So geht's:
Ermitteln der maximalen Heap-Größe, die die App verwenden kann:
Abrufen, wie viel von dem Heap Ihre App derzeit verwendet:
Abrufen, wie viel von dem Heap Ihre App jetzt verwenden kann (verfügbarer Speicher):
Und um jedes von ihnen schön zu formatieren, können Sie Folgendes verwenden:
quelle
Dies gibt die maximale Heap-Größe in Bytes zurück:
Ich habe ActivityManager.getMemoryClass () verwendet, aber auf CyanogenMod 7 (ich habe es nicht an anderer Stelle getestet) wird ein falscher Wert zurückgegeben, wenn der Benutzer die Heap-Größe manuell festlegt.
quelle
getMemoryClass
zu implizieren scheint, dass die Anzahl möglicherweise nicht mit der verfügbaren Heap-Größe für Ihr VM übereinstimmt, und das Dokument fürgetNativeHeapSize
... stillschweigend ist, denke ich wirklich, dass diesRuntime.getRuntime().maxMemory()
die beste Antwort ist.Einige Vorgänge sind schneller als Java Heap Space Manager. Durch das Verzögern von Vorgängen für einige Zeit kann Speicherplatz frei werden. Mit dieser Methode können Sie Fehler in der Heap-Größe vermeiden:
quelle
AvailableMemoryPercentage
ist nach Formel: Wie viel Speicher des Geräts ist derzeit frei.MIN_AVAILABLE_MEMORY_PERCENTAGE
ist Ihr benutzerdefinierter Parameter, ein Schwellenwert, ab dem Sie darauf warten, dass der Garbage Collector seine Aufgabe erfüllt.Asus Nexus 7 (2013) 32Gig: getMemoryClass () = 192 maxMemory () = 201326592
Ich habe den Fehler gemacht, mein Spiel auf dem Nexus 7 als Prototyp zu erstellen, und dann festgestellt, dass auf dem generischen 4.04-Tablet meiner Frau (Speicherklasse 48, maxmemory 50331648) fast sofort nicht mehr genügend Speicher vorhanden ist.
Ich muss mein Projekt umstrukturieren, um weniger Ressourcen zu laden, wenn ich feststelle, dass die Speicherklasse niedrig ist.
Gibt es in Java eine Möglichkeit, die aktuelle Heap-Größe anzuzeigen? (Ich kann es beim Debuggen deutlich in der logCat sehen, aber ich möchte eine Möglichkeit, es im Code zu sehen, um es anzupassen, z. B. wenn currentheap> (maxmemory / 2) hochwertige Bitmaps entlädt und niedrige Qualität lädt
quelle
Meinen Sie programmatisch oder nur während Sie entwickeln und debuggen? In letzterem Fall können Sie diese Informationen aus der DDMS-Perspektive in Eclipse anzeigen. Wenn Ihr Emulator (möglicherweise sogar ein angeschlossenes physisches Telefon) ausgeführt wird, werden die aktiven Prozesse in einem Fenster auf der linken Seite aufgelistet. Sie können es auswählen und es gibt eine Option zum Verfolgen der Heap-Zuordnungen.
quelle
Wert ist b
Wert ist MB
quelle
rt
? Wo wird es deklariert?