Wie kann ich den von meiner Android-Anwendung verwendeten Speicher programmgesteuert ermitteln?
Ich hoffe, es gibt eine Möglichkeit, dies zu tun. Außerdem, wie bekomme ich den freien Speicher des Telefons zu?
Wie kann ich den von meiner Android-Anwendung verwendeten Speicher programmgesteuert ermitteln?
Ich hoffe, es gibt eine Möglichkeit, dies zu tun. Außerdem, wie bekomme ich den freien Speicher des Telefons zu?
Wir haben herausgefunden, dass alle Standardmethoden, um den Gesamtspeicher des aktuellen Prozesses zu ermitteln, einige Probleme aufweisen.
Runtime.getRuntime().totalMemory()
Nur JVM-Speicher: Gibt nur JVM-Speicher zurück.ActivityManager.getMemoryInfo()
, Process.getFreeMemory()
und alles andere, was auf /proc/meminfo
- liefert Speicherinformationen über alle Prozesse zusammen (z. B. android_util_Process.cpp )Debug.getNativeHeapAllocatedSize()
- Verwendungen mallinfo()
die Informationen über Speicherzuweisungen zurückgeben, die von malloc()
und verwandte Funktionen (siehe android_os_Debug.cpp )Debug.getMemoryInfo()
- erledigt die Aufgabe, aber es ist zu langsam. Er braucht etwa 200ms en Nexus 6 für einen einzigen Anruf. Der Performance-Overhead macht diese Funktion für uns unbrauchbar, da wir sie regelmäßig aufrufen und jeder Aufruf ziemlich auffällig ist (siehe android_os_Debug.cpp )ActivityManager.getProcessMemoryInfo(int[])
- Anrufe Debug.getMemoryInfo()
intern (siehe ActivityManagerService.java )Schließlich haben wir den folgenden Code verwendet:
const long pageSize = 4 * 1024; //`sysconf(_SC_PAGESIZE)`
string stats = File.ReadAllText("/proc/self/statm");
var statsArr = stats.Split(new [] {' ', '\t', '\n'}, 3);
if( statsArr.Length < 2 )
throw new Exception("Parsing error of /proc/self/statm: " + stats);
return long.Parse(statsArr[1]) * pageSize;
Sie gibt zurück VmRSS metrisch. Weitere Einzelheiten dazu finden Sie hier: un , zwei y drei .
P.S. Ich habe bemerkt, dass das Thema immer noch einen Mangel an einer tatsächlichen und einfachen Code-Schnipsel, wie man Schätzung die private Speichernutzung des Prozesses, wenn die Leistung keine kritische Anforderung darstellt:
Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
Debug.getMemoryInfo(memInfo);
long res = memInfo.getTotalPrivateDirty();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
res += memInfo.getTotalPrivateClean();
return res * 1024L;
In Android Studio 3.0 wurde der Android-Profiler eingeführt, der Ihnen hilft zu verstehen, wie Ihre App CPU-, Speicher-, Netzwerk- und Batterieressourcen nutzt.
https://developer.Android.com/studio/profile/Android-profiler
Ich war verwirrt, als ich die Antworten las, also beschloss ich, die Dokumente zu lesen. OK, los geht's:
Sie können die native Heap-Speichergröße des Geräts mit Debuggen Objekt:
long nativeTotal = Debug.getNativeHeapSize();
long nativeFree = Debug.getNativeHeapFreeSize();
long nativeAllocated = Debug.getNativeHeapAllocatedSize();
long nativeUsed = nativeTotal - nativeFree;
Anmerkung: nativeUsed
y nativeAllocated
den gleichen Wert haben.
Speichernutzung durch Laufzeit Objekt der Anwendung, Jede Anwendung hat ein Laufzeitobjekt für den Zugriff auf ihre Schnittstelle:
Runtime runtime = Runtime.getRuntime();
long runtimeMax = runtime.maxMemory();
long runtimeTotal = runtime.totalMemory();
long runtimeFree = runtime.freeMemory();
long runtimeUsed = runtimeTotal - runtimeFree;
Sie können die Speichernutzung des Systems mit ActivityManager.MemoryInfo Objekt:
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
long systemTotal = memoryInfo.totalMem;
long systemFree = memoryInfo.availMem;
long systemUsed = systemTotal - systemFree;
Eine andere Möglichkeit, die Speichernutzung des Systems zu lesen, ist das Parsen des Inhalts der Datei /proc/meminfo Datei unter Linux.
RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r");
Pattern pattern = Pattern.compile("(\\d+)");
Matcher totalMatcher = pattern.matcher(reader.readLine());
totalMatcher.find();
long procTotal = Long.parseLong(totalMatcher.group(1)) * 1024L; // KB to B
Matcher freeMatcher = pattern.matcher(reader.readLine());
freeMatcher.find();
long procFree = Long.parseLong(freeMatcher.group(1)) * 1024L; // KB to B
long procUsed = procTotal - procFree;
OK, ich bin immer noch verwirrt. Aber das waren alle Möglichkeiten, wie man den Speicherverbrauch ermitteln kann. SIE ALLE PROTOKOLLIEREN, UM IHRE ANWENDUNG ZU DEBUGGEN !!!
Ich biete auch einen Link für jeden von ihnen, um ihre Verwendung und Informationen zu lesen.
Es gibt viele Antworten, die Ihnen sicher helfen werden, aber (nach 2 Tagen leisten und Forschung auf adb Speicher-Tools) Ich denke, ich kann mit meinem Stellungnahme auch.
Als Hackbod sagt: Würde man also den gesamten physischen Arbeitsspeicher nehmen, der tatsächlich jedem Prozess zugeordnet ist, und alle Prozesse zusammenzählen, käme man wahrscheinlich auf eine Zahl, die viel größer ist als der tatsächliche Gesamtspeicher. Es gibt also keine Möglichkeit, die genaue Menge an Speicher pro Prozess zu ermitteln.
Aber man kann sich ihr mit einer gewissen Logik nähern und ich werde sagen, wie.
Es gibt einige API wie
android.os.Debug.MemoryInfo
yActivityManager.getMemoryInfo()
die Sie vielleicht schon gelesen und benutzt haben, aber ich werde über andere Möglichkeiten sprechen
Sie müssen also erstens Root-Benutzer sein, damit es funktioniert. Rufen Sie die Konsole mit Root-Rechten auf, indem Sie Folgendes ausführen su
in Bearbeitung und erhalten seine output and input stream
. Dann passieren id\n
(eingeben) in den Ausgabestrom und schreiben ihn in die Prozessausgabe, erhält If einen Eingabestrom mit uid=0
, Sie sind Root-Benutzer.
Hier ist die Logik, die Sie im obigen Prozess verwenden werden
Wenn Sie den Ausgabestrom des Prozesses erhalten übergeben Sie den Befehl (procrank, dumpsys meminfo etc...) mit \n
anstelle von id und erhalten seine inputstream
und lesen, den Stream in Bytes[ ], Char[ ] usw. speichern. roh Daten..und fertig!!!!!
Genehmigung:
<uses-permission android:name="android.permission.FACTORY_TEST"/>
Prüfen Sie, ob Sie Root-Benutzer sind:
// su command to get root access
Process process = Runtime.getRuntime().exec("su");
DataOutputStream dataOutputStream =
new DataOutputStream(process.getOutputStream());
DataInputStream dataInputStream =
new DataInputStream(process.getInputStream());
if (dataInputStream != null && dataOutputStream != null) {
// write id to console with enter
dataOutputStream.writeBytes("id\n");
dataOutputStream.flush();
String Uid = dataInputStream.readLine();
// read output and check if uid is there
if (Uid.contains("uid=0")) {
// you are root user
}
}
Führen Sie Ihren Befehl mit su
Process process = Runtime.getRuntime().exec("su");
DataOutputStream dataOutputStream =
new DataOutputStream(process.getOutputStream());
if (dataOutputStream != null) {
// adb command
dataOutputStream.writeBytes("procrank\n");
dataOutputStream.flush();
BufferedInputStream bufferedInputStream =
new BufferedInputStream(process.getInputStream());
// this is important as it takes times to return to next line so wait
// else you with get empty bytes in buffered stream
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// read buffered stream into byte,char etc.
byte[] bff = new byte[bufferedInputStream.available()];
bufferedInputStream.read(bff);
bufferedInputStream.close();
}
}
Sie erhalten die Rohdaten in einer einzigen Zeichenkette von der Konsole und nicht in einer Instanz von einer API, die komplex zu speichern ist, da Sie sie manuell trennen müssen. .
Dies ist nur ein Versuch, bitte schlagen Sie mir vor, wenn ich etwas übersehen habe
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.