Jak mogę programowo znaleźć pamięć używaną w mojej aplikacji na Androida?
Mam nadzieję, że jest na to sposób. Dodatkowo, w jaki sposób mogę uzyskać bezpłatną pamięć telefonu?
java
android
memory
memory-management
Andrea Baccega
źródło
źródło
Odpowiedzi:
Pamiętaj, że użycie pamięci w nowoczesnych systemach operacyjnych, takich jak Linux, jest niezwykle skomplikowanym i trudnym do zrozumienia obszarem. W rzeczywistości szanse na to, że właściwie poprawnie interpretujesz otrzymane liczby, są bardzo niskie. (Prawie za każdym razem, gdy patrzę na numery wykorzystania pamięci z innymi inżynierami, zawsze trwa długa dyskusja na temat tego, co one właściwie oznaczają, co tylko prowadzi do niejasnych wniosków.)
Uwaga: mamy teraz znacznie obszerniejszą dokumentację dotyczącą zarządzania pamięcią aplikacji, która obejmuje większą część materiału tutaj i jest bardziej aktualna w stanie Androida.
Pierwszą rzeczą jest prawdopodobnie przeczytanie ostatniej części tego artykułu, w której omówiono sposób zarządzania pamięcią na Androidzie:
Zmiany interfejsu API usług począwszy od Androida 2.0
Teraz
ActivityManager.getMemoryInfo()
jest nasz interfejs API najwyższego poziomu do sprawdzania ogólnego zużycia pamięci. Ma to na celu przede wszystkim pomóc aplikacji ocenić, jak blisko system nie ma już pamięci dla procesów w tle, a tym samym musi zacząć zabijać potrzebne procesy, takie jak usługi. W przypadku czystych aplikacji Java powinno to być mało przydatne, ponieważ limit sterty Java jest częściowo stosowany, aby jedna aplikacja nie była w stanie obciążać systemu do tego momentu.Przechodząc na niższy poziom, możesz użyć interfejsu API debugowania, aby uzyskać nieprzetworzone informacje o zużyciu pamięci na poziomie jądra: android.os.Debug.MemoryInfo
Uwaga: począwszy od wersji 2.0 istnieje również interfejs API,
ActivityManager.getProcessMemoryInfo
aby uzyskać informacje o innym procesie: ActivityManager.getProcessMemoryInfo (int [])Zwraca niskopoziomową strukturę MemoryInfo ze wszystkimi tymi danymi:
Ale, co jest różnica między
Pss
,PrivateDirty
iSharedDirty
... no teraz zaczyna się zabawa.Dużo pamięci w systemie Android (i ogólnie w systemach Linux) jest faktycznie współdzielonych przez wiele procesów. Tak więc, ile pamięci zajmuje proces, nie jest do końca jasne. Dodanie tego stronicowania na dysk (nie mówiąc już o zamianie, której nie używamy na Androidzie), a jest jeszcze mniej jasne.
Zatem jeśli weźmiesz całą fizyczną pamięć RAM faktycznie zmapowaną do każdego procesu i zsumujesz wszystkie procesy, prawdopodobnie skończyłbyś z liczbą znacznie większą niż rzeczywista całkowita pamięć RAM.
Pss
Liczba jest metryka to Oblicza jądra, która bierze pod dzielenia pamięci konto - w zasadzie każdej strony pamięci RAM w procesie jest skalowany przez stosunek liczby innych procesów również przy użyciu tej strony. W ten sposób możesz (teoretycznie) dodać pss we wszystkich procesach, aby zobaczyć całkowitą pamięć RAM, której używają, i porównać pss między procesami, aby uzyskać przybliżone wyobrażenie o ich względnej wadze.Inną interesującą miarą jest tutaj
PrivateDirty
ilość pamięci RAM wewnątrz procesu, której nie można przywołać na dysk (nie jest ona wspierana tymi samymi danymi na dysku) i nie jest współdzielona z żadnymi innymi procesami. Innym sposobem, aby na to spojrzeć, jest pamięć RAM, która stanie się dostępna dla systemu, gdy proces ten zniknie (i prawdopodobnie szybko przejdzie do pamięci podręcznej i innych zastosowań).To właściwie interfejsy API SDK do tego. Jest jednak więcej rzeczy, które możesz zrobić jako programista na swoim urządzeniu.
Używając
adb
, możesz uzyskać wiele informacji na temat wykorzystania pamięci przez uruchomiony system. Często stosowanym jest polecenie,adb shell dumpsys meminfo
które wypluwa mnóstwo informacji na temat wykorzystania pamięci przez każdy proces Java, zawierające powyższe informacje, a także wiele innych rzeczy. Możesz także podać nazwę lub numer pid pojedynczego procesu, aby zobaczyć, na przykładadb shell dumpsys meminfo system
podaj mi proces systemowy:Górna sekcja jest główna, gdzie
size
jest całkowity rozmiar w przestrzeni adresowej konkretnej sterty,allocated
jest to KB rzeczywistych przydziałów, które stos uważa, że ma,free
to pozostała wolna KB, którą sterty ma dla dodatkowych przydziałów,pss
ipriv dirty
są takie same jak omówiono wcześniej dla stron powiązanych z każdym ze stosów.Jeśli chcesz tylko sprawdzić wykorzystanie pamięci we wszystkich procesach, możesz użyć polecenia
adb shell procrank
. Wynik tego w tym samym systemie wygląda następująco:W tym przypadku kolumny
Vss
iRss
są w zasadzie szumem (są to prosta przestrzeń adresowa i użycie pamięci RAM przez proces, gdzie jeśli zsumujesz użycie pamięci RAM w procesach, otrzymasz absurdalnie dużą liczbę).Pss
jest jak widzieliśmy wcześniej iUss
jestPriv Dirty
.Interesująca rzecz do odnotowania tutaj:
Pss
iUss
są nieco (lub więcej niż nieco) inne niż to, co widzieliśmymeminfo
. Dlaczego? Cóż, procrank używa innego mechanizmu jądra do gromadzenia danych niżmeminfo
robi i dają one nieco inne wyniki. Dlaczego? Szczerze mówiąc nie mam pojęcia. Wydaje mi się, żeprocrank
może być dokładniejszy ... ale tak naprawdę, po prostu zostaw punkt: „weź wszelkie informacje o pamięci, które otrzymujesz z dodatkiem ziarenka soli; często bardzo duże ziarno”.Wreszcie istnieje polecenie,
adb shell cat /proc/meminfo
które daje podsumowanie ogólnego wykorzystania pamięci przez system. Jest tu wiele danych, tylko kilka pierwszych liczb, które warto omówić (i pozostałe są zrozumiałe dla kilku osób, a moje pytania o te kilka osób na ich temat często powodują sprzeczne wyjaśnienia):MemTotal
jest całkowitą ilością pamięci dostępnej dla jądra i przestrzeni użytkownika (często mniejszą niż faktyczna fizyczna pamięć RAM urządzenia, ponieważ część tej pamięci RAM jest potrzebna na radio, bufory DMA itp.).MemFree
to ilość pamięci RAM, która w ogóle nie jest używana. Liczba, którą tu widzisz, jest bardzo wysoka; zwykle w systemie Android byłoby to zaledwie kilka MB, ponieważ staramy się wykorzystywać dostępną pamięć, aby procesy działałyCached
jest używana pamięć RAM dla pamięci podręcznych systemu plików i innych podobnych rzeczy. Typowe systemy będą musiały mieć około 20 MB, aby uniknąć wpadania w zły stan stronicowania; zabójca pamięci poza systemem Android jest dostosowany do konkretnego systemu, aby upewnić się, że procesy w tle zostaną zabite, zanim pamięć RAM w pamięci podręcznej zostanie przez nich zbytnio zużyta, aby spowodować takie stronicowanie.źródło
Tak, możesz uzyskać informacje o pamięci programowo i zdecydować, czy wykonać intensywną pracę.
Uzyskaj rozmiar stosu maszyn wirtualnych, dzwoniąc:
Uzyskaj przydzieloną pamięć VM, dzwoniąc:
Uzyskaj limit rozmiaru stosu maszyn wirtualnych, dzwoniąc:
Uzyskaj natywną pamięć przydzieloną, dzwoniąc:
Zrobiłem aplikację, aby dowiedzieć się zachowanie OutOfMemoryError i monitorować użycie pamięci.
https://play.google.com/store/apps/details?id=net.coocood.oomresearch
Możesz pobrać kod źródłowy na https://github.com/coocood/oom-research
źródło
To jest praca w toku, ale tego nie rozumiem:
Dlaczego PID nie jest mapowany na wynik w activityManager.getProcessMemoryInfo ()? Najwyraźniej chcesz, aby uzyskane dane były znaczące, więc dlaczego Google tak trudno skorelowało wyniki? Obecny system nawet nie działa dobrze, jeśli chcę przetworzyć całe użycie pamięci, ponieważ zwrócony wynik to tablica obiektów android.os.Debug.MemoryInfo, ale żaden z tych obiektów nie mówi ci, z którymi pidami są skojarzone. Jeśli po prostu przekażesz tablicę wszystkich ofert, nie będziesz w stanie zrozumieć wyników. Rozumiem, że jest użyteczny, dlatego nie ma sensu przekazywać więcej niż jednego pid na raz, a jeśli tak, to po co to robić, aby activityManager.getProcessMemoryInfo () pobierał tylko tablicę int?
źródło
Hackbod's jest jedną z najlepszych odpowiedzi na temat przepełnienia stosu. Rzuca światło na bardzo niejasny obiekt. Bardzo mi pomogło.
Innym naprawdę przydatnym źródłem jest ten film, który musisz zobaczyć: Google I / O 2011: Zarządzanie pamięcią dla aplikacji na Androida
AKTUALIZACJA:
Process Stats, usługa pozwalająca odkryć, w jaki sposób aplikacja zarządza pamięcią, wyjaśniona na blogu Statystyki procesu: Zrozumienie, w jaki sposób Twoja aplikacja korzysta z pamięci RAM przez Dianne Hackborn:
źródło
Android Studio 0.8.10+ wprowadziło niezwykle przydatne narzędzie o nazwie Memory Monitor .
Do czego służy:
Rysunek 1. Wymuszanie zdarzenia GC (Garbage Collection) w Monitorze pamięci systemu Android
Korzystając z niej, możesz uzyskać wiele dobrych informacji na temat zużycia pamięci RAM w czasie rzeczywistym przez aplikację.
źródło
1) Chyba nie, przynajmniej nie z Javy.
2)
źródło
Okazało się, że wszystkie standardowe sposoby uzyskania całkowitej pamięci bieżącego procesu mają pewne problemy.
Runtime.getRuntime().totalMemory()
: zwraca tylko pamięć JVMActivityManager.getMemoryInfo()
,Process.getFreeMemory()
I cokolwiek innego na podstawie/proc/meminfo
- zwraca informacje o pamięci wszystkich procesów połączonych (np android_util_Process.cpp )Debug.getNativeHeapAllocatedSize()
- używa,mallinfo()
które zwracają tylko informacje o przydziałach pamięci wykonywanych przezmalloc()
i powiązanych funkcjach (patrz android_os_Debug.cpp )Debug.getMemoryInfo()
- wykonuje swoją pracę, ale jest zbyt wolna. Pojedyncza rozmowa trwa około 200 ms na Nexusie 6 . Narzut związany z wydajnością sprawia, że ta funkcja jest dla nas bezużyteczna, ponieważ nazywamy ją regularnie, a każde połączenie jest dość zauważalne (patrz android_os_Debug.cpp )ActivityManager.getProcessMemoryInfo(int[])
- wywołujeDebug.getMemoryInfo()
wewnętrznie (patrz ActivityManagerService.java )W końcu użyliśmy następującego kodu:
Zwraca metrykę VmRSS . Możesz znaleźć więcej szczegółów na ten temat tutaj: jeden , dwa i trzy .
PS Zauważyłem, że temat nadal ma brak rzeczywistej i prosty fragment kodu, w jaki sposób oszacować prywatnego wykorzystania pamięci procesu, jeśli wydajność nie jest krytyczny wymóg:
źródło
W Android Studio 3.0 wprowadzono Android-profiler, aby pomóc Ci zrozumieć, w jaki sposób aplikacja wykorzystuje zasoby procesora, pamięci, sieci i baterii.
https://developer.android.com/studio/profile/android-profiler
źródło
Istnieje wiele odpowiedzi powyżej, które na pewno ci pomogą, ale (po 2 dniach zakupu i badaniach nad narzędziami pamięci adb) myślę, że mogę również pomóc z moją opinią .
Jak mówi Hackbod: Zatem jeśli weźmiesz całą fizyczną pamięć RAM faktycznie zamapowaną do każdego procesu i zsumujesz wszystkie procesy, prawdopodobnie skończyłbyś z liczbą znacznie większą niż rzeczywista całkowita pamięć RAM. więc nie ma możliwości uzyskania dokładnej ilości pamięci na proces.
Ale możesz się do tego zbliżyć za pomocą logiki ... a ja powiem jak ...
Po pierwsze, musisz być użytkownikiem root, aby działał. Wejdź do konsoli z uprawnieniami roota, wykonując
su
proces i zdobądź jąoutput and input stream
. Następnie przekażid\n
(enter) w ouputstream i zapisz go do przetwarzania danych wyjściowych. Jeśli otrzymasz strumień wejściowy zawierającyuid=0
, jesteś użytkownikiem root.Oto logika, której użyjesz w powyższym procesie
Kiedy pojawi się ouputstream procesu , wydaj polecenie (procrank, dumpsys meminfo itp.)
\n
Zamiast zamiast id i pobierz goinputstream
i przeczytaj, przechowuj strumień w bajtach [], char [] itd. Użyj surowych danych .. i są skończone!!!!!pozwolenie :
Sprawdź, czy jesteś użytkownikiem root:
Wykonaj polecenie za pomocą
su
logcat:
To tylko próba, proszę zasugerować mi, jeśli coś przeoczyłem
źródło