Bagaimana cara mendapatkan penggunaan memori saat ini di android?

108

Saya telah menggunakan / proc / meminfo dan mem-parsed command response. Namun hasilnya menunjukkan bahwa:

MemTotal: 94348 kB MemFree: 5784 kB

cara. itu menunjukkan hanya ada 5MB memori kosong. Apakah mungkin dengan ponsel android? Hanya ada 5-6 aplikasi yang diinstal di ponsel saya dan tidak ada tugas lain yang sedang berjalan. tetapi tetap saja perintah ini menunjukkan hanya ada sedikit memori bebas.

Adakah yang bisa menjelaskan ini? atau apakah ada cara lain untuk mendapatkan penggunaan memori di android?

Badal
sumber
2
Apakah Anda mencoba melihat memori gratis per perangkat, atau per aplikasi? Jika per aplikasi, maka perlu dihitung di heap a-la Debug.getNativeHeapFreeSize().
IgorGanapolsky
1
Untuk menghitung memori bebas (dalam RAM) menggunakan / proc / meminfo, Anda harus mendapatkan kumpulan MemFree , Buffer , Cache , dan SwapCached . Ada API untuk tujuan ini yang disediakan oleh Android yang bekerja di API 16 dan di lingkungan. Meminfo berguna jika Anda menargetkan API yang lebih lama.
AB

Jawaban:

174

PERHATIAN: Jawaban ini mengukur penggunaan memori / ketersediaan DEVICE. Ini BUKAN yang tersedia untuk aplikasi Anda. Untuk mengukur apa yang sedang dilakukan APP Anda, dan DIPERBOLEHKAN untuk melakukannya, Gunakan jawaban pengembang android .


Dokumen Android - ActivityManager.MemoryInfo

  1. parse / proc / meminfo. Anda dapat menemukan kode referensi di sini: Dapatkan Penggunaan Memori di Android

  2. gunakan kode di bawah ini dan dapatkan RAM saat ini:

    MemoryInfo mi = new MemoryInfo();
    ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    activityManager.getMemoryInfo(mi);
    double availableMegs = mi.availMem / 0x100000L;
    
    //Percentage can be calculated for API 16+
    double percentAvail = mi.availMem / (double)mi.totalMem * 100.0;

Penjelasan tentang angka 0x100000L

1024 bytes      == 1 Kibibyte 
1024 Kibibyte   == 1 Mebibyte

1024 * 1024     == 1048576
1048576         == 0x100000

Cukup jelas bahwa angka tersebut digunakan untuk mengonversi dari byte ke mebibyte

PS: kita hanya perlu menghitung memori total sekali. jadi panggil poin 1 hanya sekali dalam kode Anda dan setelah itu, Anda dapat memanggil kode poin 2 berulang-ulang.

Badal
sumber
Saya ingin memeriksa ukuran memori. Apa itu MemoryInfo?
Piraba
PIraba, Kelas API androidnya. Lihat di sini developer.android.com/reference/android/app/… .
Badal
@SanjayJoshi Itu karena variabel availMem berisi memori dalam byte. 1024 Bytes sama dengan 1 KiloByte dan 1024 kilobyte sama dengan 1 MegaByte. Jadi 1024 * 1024 sama dengan 1048576
Rolf ツ
2
Konversikan menjadi dua kali lipat di atas, jika tidak, percentAvail akan menjadi 0
blueether
1
@Rolf ツ maaf tapi 1024 byte sama dengan satu Kibibyte dan 1024 Kibibyte adalah satu MibiByte. Kilo dan Mega adalah prefiks desimal. 1000 byte = 1 Kilobyte. Ini juga salah dijelaskan dalam jawaban.
JacksOnF1re
88

Itu tergantung pada definisi Anda tentang kueri memori yang ingin Anda dapatkan.


Biasanya, Anda ingin mengetahui status memori heap, karena jika memori menggunakan terlalu banyak, Anda mendapatkan OOM dan merusak aplikasi.

Untuk ini, Anda dapat memeriksa nilai berikutnya:

final Runtime runtime = Runtime.getRuntime();
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

Semakin banyak variabel "usedMemInMB" mendekati "maxHeapSizeInMB", semakin mendekati availHeapSizeInMBnol, semakin dekat Anda mendapatkan OOM. (Karena fragmentasi memori, Anda mungkin mendapatkan OOM SEBELUM ini mencapai nol.)

Itu juga yang ditunjukkan oleh alat DDMS untuk penggunaan memori.


Atau, ada penggunaan RAM yang sebenarnya, yaitu berapa banyak yang digunakan seluruh sistem - lihat jawaban yang diterima untuk menghitungnya.


Pembaruan: karena Android O membuat aplikasi Anda juga menggunakan RAM asli (setidaknya untuk penyimpanan Bitmaps, yang biasanya merupakan alasan utama penggunaan memori yang besar), dan bukan hanya heap, banyak hal telah berubah, dan Anda mendapatkan lebih sedikit OOM (karena heap tidak lagi mengandung bitmap, periksa di sini ), tetapi Anda harus tetap mengawasi penggunaan memori jika Anda curiga Anda mengalami kebocoran memori. Di Android O, jika Anda memiliki kebocoran memori yang seharusnya menyebabkan OOM pada versi yang lebih lama, tampaknya itu hanya akan macet tanpa Anda dapat menangkapnya. Berikut cara memeriksa penggunaan memori:

val nativeHeapSize = Debug.getNativeHeapSize()
val nativeHeapFreeSize = Debug.getNativeHeapFreeSize()
val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize

Tapi saya percaya mungkin yang terbaik adalah menggunakan profiler dari IDE, yang menampilkan data secara real time, menggunakan grafik.

Jadi, kabar baik di Android O adalah jauh lebih sulit untuk mendapatkan error karena OOM menyimpan terlalu banyak bitmap besar, tetapi berita buruknya adalah menurut saya tidak mungkin untuk menangkap kasus seperti itu selama runtime.


EDIT: tampaknya Debug.getNativeHeapSize() berubah seiring waktu, karena ini menunjukkan kepada Anda total memori maksimal untuk aplikasi Anda. Jadi fungsi tersebut hanya digunakan untuk profiler, untuk menunjukkan seberapa banyak aplikasi Anda digunakan.

Jika Anda ingin mendapatkan total nyata dan RAM asli yang tersedia, gunakan ini:

val memoryInfo = ActivityManager.MemoryInfo()
(getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(memoryInfo)
val nativeHeapSize = memoryInfo.totalMem
val nativeHeapFreeSize = memoryInfo.availMem
val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize
Log.d("AppLog", "total:${Formatter.formatFileSize(this, nativeHeapSize)} " +
        "free:${Formatter.formatFileSize(this, nativeHeapFreeSize)} " +
        "used:${Formatter.formatFileSize(this, usedMemInBytes)} ($usedMemInPercentage%)")
pengembang android
sumber
Wow. Sangat sederhana, namun sangat benar!
Berlari
apa penggunaan memori sebenarnya? jadi usedMemInMB dalam hal ini bukan penggunaan memori nyata dari aplikasi? Ketika saya menggunakan kode ini, ini menunjukkan bahwa penggunaan saya seperti 50mb tetapi ketika saya pergi ke pengaturan telepon dan melihat penggunaan memori di sana, aplikasi saya menunjukkan 100mb. mengapa ada perbedaan ini?
batmaci
1
@batmaci Memori heap hanyalah sebagian dari penggunaan memori total aplikasi. Ada juga penggunaan memori asli, yang biasanya digunakan untuk Halaman Web, game, dan beberapa tujuan berat. Biasanya aplikasi hanya perlu melihat pada memori heap, karena cukup rendah dibandingkan dengan RAM perangkat, dan jika mencapai itu, aplikasi akan macet (meskipun ada banyak RAM kosong).
Pengembang android
Ini adalah potongan kode yang sempurna, sangat berguna untuk memeriksa OOM, terima kasih banyak.
aolphn
@AlphaOF Terima kasih, tetapi banyak hal telah berubah di Android O. Saya telah memperbarui jawaban untuk menyesuaikan dengan situasi di sana.
Pengembang android
29

Berikut ini cara menghitung penggunaan memori dari aplikasi yang sedang berjalan :

public static long getUsedMemorySize() {

    long freeSize = 0L;
    long totalSize = 0L;
    long usedSize = -1L;
    try {
        Runtime info = Runtime.getRuntime();
        freeSize = info.freeMemory();
        totalSize = info.totalMemory();
        usedSize = totalSize - freeSize;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return usedSize;

}
Sharmilee
sumber
4
Ini adalah pendekatan sederhana, tetapi seperti yang ditunjukkan pada dokumentasi, metode freeMemory () kelas Runtime, mengembalikan memori yang tersedia untuk program atau aplikasi saat ini. Jadi berhati-hatilah saat menggunakan.
Aksel Fatih
2
@ Peter - Ya, ini "salah" karena menjawab pertanyaan yang berbeda dari yang diminta. Di sisi lain, ini adalah "tepat" untuk apa yang biasanya perlu diketahui oleh pengembang aplikasi: kondisi memori secara keseluruhan pada DEVICE jarang menjadi masalah - jika pengguna telah menjalankan banyak aplikasi, OS harus memanfaatkan sebagian besar memorinya - jika tidak maka tidak efisien. OS perlu tahu apa yang diberikan jawaban yang diterima, untuk mengetahui kapan harus mulai mematikan aplikasi yang belum digunakan baru-baru ini. Tetapi seorang pemrogram aplikasi perlu tahu apa jawaban INI (dan jawaban serupa pengembang android) memberi tahu Anda, vs. runtime.maxMemory.
ToolmakerSteve
Solusi ini hanya berfungsi pada memori yang diekspos ke aplikasi oleh Runtime. Ini tidak memberikan wawasan tentang seluruh memori sistem seperti yang dibutuhkan OP.
AB
Pada banyak perangkat (misalnya Xiaomi) Runtime.freeMemory()mengembalikan 0 dan hanya Runtime.totalMemory()mengembalikan memori yang dialokasikan saat ini.
artem
17

Cara lain (saat ini menunjukkan 25MB gratis di G1 saya):

MemoryInfo mi = new MemoryInfo();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 1048576L;
yanchenko
sumber
Hai Alex, Terima kasih banyak atas bantuan Anda! 1 pertanyaan lagi. Kode ini memberi saya RAM yang tersedia. Saya juga ingin menampilkan Total RAM. Bagaimana cara mendapatkannya?
Badal
@Badal Saya tidak tahu API Java untuk itu. Tetap gunakan parsing / proc / meminfo.
yanchenko
12

Filosofi manajemen memori Linux adalah "Memori bebas adalah memori yang terbuang".

Saya berasumsi bahwa dua baris berikutnya akan menunjukkan berapa banyak memori yang ada di "Buffer" dan berapa banyak yang "Cache". Meskipun ada perbedaan di antara keduanya (tolong jangan tanya apa perbedaannya :) keduanya secara kasar menambah jumlah memori yang digunakan untuk menyimpan data file dan metadata.

Panduan yang jauh lebih berguna untuk membebaskan memori di sistem Linux adalah free(1)perintah; di desktop saya, ini melaporkan informasi seperti ini:

$ gratis -m
             total digunakan cache buffer bersama gratis
Mem: 5980 1055 4924 0 91374
- / + buffer / cache: 589 5391
Tukar: 6347 0 6347

+/- buffer / cache: line adalah garis ajaib, ia melaporkan bahwa saya benar-benar memiliki sekitar 589 MB memori proses yang diperlukan secara aktif, dan sekitar 5391 MB memori 'gratis', dalam arti bahwa 91 + 374 MB buffer / memori cache dapat dibuang jika memori dapat digunakan secara lebih menguntungkan di tempat lain.

(Mesin saya telah menyala sekitar tiga jam, hampir tidak melakukan apa pun kecuali stackoverflow, itulah sebabnya saya memiliki begitu banyak memori kosong.)

Jika Android tidak disertakan free(1), Anda dapat menghitung sendiri dengan /proc/meminfofile tersebut; Saya hanya suka free(1)format keluarannya. :)

sarnold
sumber
1
@Igor, maka Anda akan menginginkannya cat /proc/meminfo. Ini jauh lebih detail, tapi MemFree. Buffers, dan Cachedmungkin baris yang paling penting.
sarnold
6

Saya merujuk beberapa tulisan.

referensi:

Metode getMemorySize () ini mengembalikan MemorySize yang memiliki ukuran memori total dan gratis.
Saya tidak percaya kode ini dengan sempurna.
Kode ini sedang diuji pada LG G3 cat.6 (v5.0.1)

    private MemorySize getMemorySize() {
        final Pattern PATTERN = Pattern.compile("([a-zA-Z]+):\\s*(\\d+)");

        MemorySize result = new MemorySize();
        String line;
        try {
            RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r");
            while ((line = reader.readLine()) != null) {
                Matcher m = PATTERN.matcher(line);
                if (m.find()) {
                    String name = m.group(1);
                    String size = m.group(2);

                    if (name.equalsIgnoreCase("MemTotal")) {
                        result.total = Long.parseLong(size);
                    } else if (name.equalsIgnoreCase("MemFree") || name.equalsIgnoreCase("Buffers") ||
                            name.equalsIgnoreCase("Cached") || name.equalsIgnoreCase("SwapFree")) {
                        result.free += Long.parseLong(size);
                    }
                }
            }
            reader.close();

            result.total *= 1024;
            result.free *= 1024;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    private static class MemorySize {
        public long total = 0;
        public long free = 0;
    }

Saya tahu bahwa Pattern.compile () mahal biayanya jadi Anda dapat memindahkan kodenya ke anggota kelas.

Hogun
sumber
3

Saya melihat Pohon Sumber Android.

Di dalam com.android.server.am. ActivityManagerService.java (layanan internal yang diekspos oleh android.app. ActivityManager ).

public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
    final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
    final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
    outInfo.availMem = Process.getFreeMemory();
    outInfo.totalMem = Process.getTotalMemory();
    outInfo.threshold = homeAppMem;
    outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
    outInfo.hiddenAppThreshold = hiddenAppMem;
    outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
            ProcessList.SERVICE_ADJ);
    outInfo.visibleAppThreshold = mProcessList.getMemLevel(
            ProcessList.VISIBLE_APP_ADJ);
    outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
            ProcessList.FOREGROUND_APP_ADJ);
}

Di dalam android.os. Process.java

/** @hide */
public static final native long getFreeMemory();

/** @hide */
public static final native long getTotalMemory();

Ini memanggil metode JNI dari android_util_Process.cpp

Kesimpulan

MemoryInfo.availMem = MemFree + Tersimpan dalam cache di / proc / meminfo.

Catatan

Total Memori ditambahkan di API level 16.

ragazenta
sumber
1

Anda juga dapat menggunakan alat DDMS yang merupakan bagian dari SDK Android itu sendiri. ini membantu dalam mendapatkan alokasi memori dari kode java dan kode c / c ++ asli juga.

vsmph
sumber
0
public static boolean isAppInLowMemory(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);

    return memoryInfo.lowMemory;
}
iMobaio
sumber
0
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

Ini adalah kode yang aneh. Ini mengembalikan MaxMemory - (totalMemory - freeMemory). Jika freeMemory sama dengan 0, maka kode akan mengembalikan MaxMemory - totalMemory, jadi bisa lebih atau sama dengan 0. Mengapa freeMemory tidak digunakan?

Andrey
sumber
0

Berikut cara lain untuk melihat penggunaan memori aplikasi Anda:

adb shell dumpsys meminfo <com.package.name> -d

Output sampel:

Applications Memory Usage (kB):
Uptime: 2896577 Realtime: 2896577

** MEMINFO in pid 2094 [com.package.name] **
                   Pss  Private  Private  Swapped     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap     3472     3444        0        0     5348     4605      102
  Dalvik Heap     2349     2188        0        0     4640     4486      154
 Dalvik Other     1560     1392        0        0
        Stack      772      772        0        0
    Other dev        4        0        4        0
     .so mmap     2749     1040     1220        0
    .jar mmap        1        0        0        0
    .apk mmap      218        0       32        0
    .ttf mmap       38        0        4        0
    .dex mmap     3161       80     2564        0
   Other mmap        9        4        0        0
      Unknown       76       76        0        0
        TOTAL    14409     8996     3824        0     9988     9091      256

 Objects
               Views:       30         ViewRootImpl:        2
         AppContexts:        4           Activities:        2
              Assets:        2        AssetManagers:        2
       Local Binders:       17        Proxy Binders:       21
    Death Recipients:        7
     OpenSSL Sockets:        0

 SQL
         MEMORY_USED:        0
  PAGECACHE_OVERFLOW:        0          MALLOC_SIZE:        0

Untuk penggunaan memori secara keseluruhan:

adb shell dumpsys meminfo

https://developer.android.com/studio/command-line/dumpsys#meminfo

pengguna1506104
sumber