How to get current memory usage in android?
Asked Answered
I

12

136

I have used /proc/meminfo and parsed command response.however it result shows that :

MemTotal: 94348 kB MemFree: 5784 kB

means. it shows there is only 5MB free memory. Is it possible with android mobile? There is only 5-6 application installed on my mobile and no other task is running. but still this command shows there is very little free memory.

Can somebody clarify this? or is there any other way of getting memory usage in android?

Inhaler answered 3/7, 2010 at 7:28 Comment(2)
Are you trying to see free memory per device, or per app? If per app, then it needs to be calculated on the heap a-la Debug.getNativeHeapFreeSize().Radiocommunication
To calculate free memory (in RAM) using /proc/meminfo you have to get the aggregate of MemFree, Buffers, Cached and SwapCached. There is an API for this purpose provided by Android which works on API 16 and on wards. Meminfo is helpful if you are targeting older APIs.Burtis
I
190

CAUTION: This answer measures memory usage/available of the DEVICE. This is NOT what is available to your app. To measure what your APP is doing, and is PERMITTED to do, Use android developer's answer.


Android docs - ActivityManager.MemoryInfo

  1. parse /proc/meminfo command. You can find reference code here: Get Memory Usage in Android

  2. use below code and get current RAM:

    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;
    

Explanation of the number 0x100000L

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

1024 * 1024     == 1048576
1048576         == 0x100000

It's quite obvious that the number is used to convert from bytes to mebibyte

P.S: we need to calculate total memory only once. so call point 1 only once in your code and then after, you can call code of point 2 repetitively.

Inhaler answered 3/7, 2010 at 7:29 Comment(9)
I want to check the memory size.What is the MemoryInfo?Uvula
PIraba, Its android API class. Check it here developer.android.com/reference/android/app/….Inhaler
@SanjayJoshi That's because the availMem variable contains the memory in bytes. 1024 Bytes equals 1 KiloByte and 1024 kilobytes equals 1 MegaByte. So 1024 * 1024 equals 1048576Disclamation
It looks like working correctly... Still I didn't get why the second line of "/proc/meminfo"(free memory) is returning so little among of ram.Crush
What is avilMem? How can we get it?Nonproductive
You can get availMem by using MemoryInfo class. Check it here javadox.com/com.google.android/android/4.1.1.4/android/app/…Inhaler
Convert to double above, else percentAvail will be 0Tarnish
@Rolfツ sorry but 1024 bytes equals one Kibibyte and 1024 Kibibyte are one MibiByte. Kilo and Mega are decimal prefixes. 1000 byte = 1 Kilobyte. This is also wrong explained in the answer.Prolific
The equation for calculating the percentage should be as below: double percentAvail = (mi.availMem * 100.0) / mi.totalMem;Nerty
S
128

It depends on your definition of what memory query you wish to get.


Usually, you'd like to know the status of the heap memory, since if it uses too much memory, you get OOM and crash the app.

For this, you can check the next values:

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

The more the "usedMemInMB" variable gets close to "maxHeapSizeInMB", the closer availHeapSizeInMB gets to zero, the closer you get OOM. (Due to memory fragmentation, you may get OOM BEFORE this reaches zero.)

That's also what the DDMS tool of memory usage shows.


Alternatively, there is the real RAM usage, which is how much the entire system uses - see accepted answer to calculate that.


Update: since Android O makes your app also use the native RAM (at least for Bitmaps storage, which is usually the main reason for huge memory usage), and not just the heap, things have changed, and you get less OOM (because the heap doesn't contain bitmaps anymore,check here), but you should still keep an eye on memory use if you suspect you have memory leaks. On Android O, if you have memory leaks that should have caused OOM on older versions, it seems it will just crash without you being able to catch it. Here's how to check for memory usage:

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

But I believe it might be best to use the profiler of the IDE, which shows the data in real time, using a graph.

So the good news on Android O is that it's much harder to get crashes due to OOM of storing too many large bitmaps, but the bad news is that I don't think it's possible to catch such a case during runtime.


EDIT: seems Debug.getNativeHeapSize() changes over time, as it shows you the total max memory for your app. So those functions are used only for the profiler, to show how much your app is using.

If you want to get the real total and available native RAM , use this:

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%)")
Slipsheet answered 9/10, 2013 at 8:55 Comment(17)
Wow. So simple, yet so true!Haunted
what is the real memory usage? so usedMemInMB in this case is not real memory usage of the app? When I use this code, it shows me usage is like 50mb but when I go to phone settings and see the memory usage there, my app shows 100mb. why is this difference?Holophytic
@batmaci Heap memory is just a part of the total memory usage of the app. There is also the native memory usage, which is usually be used for Webpages, games and some heavy purposes. Usually apps need to look only on the heap memory, because it's quite low compared to the device RAM, and if they reach it, the app will crash (even if there is plenty of free RAM).Slipsheet
It's a perfect code snippet,very useful for checking OOM,thanks so much.Agglutinate
@AlphaOF Thank you, but things have changed on Android O. I've updated the answer to match the situation there.Slipsheet
By the way, the memory info getting from code is different with memory profiler's,do you know why?Agglutinate
@Aolphn No. That's why I wrote the question there. I wanted a consistent and reliable way to get it. No idea which one is correct now. Maybe I should write about it as a bug here: issuetracker.google.com/issuesSlipsheet
@androiddeveloper okay,any way thanks again,hope somebody can answer this question.Agglutinate
Caveat: as pointed out in this comment, the values given will be in Mibibytes not MegabytesGeisel
@RupertRawnsley So? that's the correct way things should be. Not 1,000 . We should always show the correct, exact, number of bytes. If you insist on other numbers, use them instead. This is not a disadvantage here.Slipsheet
@androiddeveloper The suffix MB in the variable name implies the value stored in that variable is in Megabytes, but it isn't. The symbol for Mebibytes is MiB so you should either use that for the suffix or divide by 1000000 instead. I appreciate it sounds pedantic, but surely this is the place to be precise.Geisel
@RupertRawnsley In the context of what we talk here, we should always use the correct values. MB in the real form means 1024*1024 bytes and KB is 1024 bytes. Look at wikipedia : en.wikipedia.org/wiki/Kilobyte . Again, this is not meant to be shown to users. It's for developers only. Developers should never use 1000 forms. To format it for users, show the terms you talk about. To developers, always use the real values. Otherwise you can confuse numbers calculations. Remember accidents in engineering when using the wrong unitsSlipsheet
@androiddeveloper The article you link to literally says a kilobyte is 1000 bytes.Geisel
@RupertRawnsley It says "In some areas of information technology, particularly in reference to digital memory capacity, kilobyte instead denotes 1024 (2^10) bytes. This arises from the powers-of-two sizing common to memory circuit design. In this context, the symbols K and KB are often used." . You can also read this: en.wikipedia.org/wiki/Megabyte . So again, as long as you want to be technical and precise, use power of 2. If you want to show to users, it's your choice what to use. Just as scientists use meters instead of feet, we should use power of 2 and not of 10.Slipsheet
@RupertRawnsley Here, if you wish to show it to users, use ` Formatter.formatFileSize` . For example, using Formatter.formatFileSize(this, 64 * 1024 * 1024) will show 67MB , which is what you get by dividing by 1000*1000 . If you want to show it differently, check this : https://mcmap.net/q/17161/-how-can-i-convert-byte-size-into-a-human-readable-format-in-javaSlipsheet
@androiddeveloper It sounds like you're arguing the same thing as RupertRawnsley, but disagreeing somehow. The IEC recommends using MiB (Mebibyte) for 1024*1024 bytes to avoid all confusion in technical communication. This is because MB (Megabyte) is overloaded, and means different things to different people, so the IEC also recommended using that only for 1000*1000 bytes. Rupert is saying whilst we have the opportunity, we should use MiB as it's unambiguous. You're arguing that in this context MB=1024*1024 bytes is assumed, but that seems worse than just using MiB, imo. Admittedly pedantic.Maiamaiah
I think val nativeHeapFreeSize = Debug.getNativeHeapFreeSize() and val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize can be simplified by calling directly val usedMemInBytes = Debug.getNativeHeapAllocatedSize()Cesta
H
32

Here is a way to calculate memory usage of currently running application:

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;

}
Haerr answered 30/10, 2012 at 7:40 Comment(4)
It is a simple approach, but as it was indicated at the documentation, the Runtime class freeMemory() method, returns the available memory for the current program or application. So be aware of that while using.Ultraconservative
@Peter - Yes, it is "wrong" in that it answers a different question than was asked. On the other hand, this is "right" for what an app developer usually needs to know: it rarely matters what the overall state of memory on the DEVICE is - if user has run lots of apps, the OS should make use of most of its memory - otherwise it is being inefficient. OS needs to know what the accepted answer gives, to know when to start killing apps that haven't been used recently. But an app programmer needs to know what THIS answer (and android developer's similar answer) tells you, vs. runtime.maxMemory.Chud
This solutions merely works on the memory exposed to the app by Runtime. This does not give insight about whole system memory as OP requires.Burtis
On many devices (e.g. Xiaomi) Runtime.freeMemory() returns 0 and Runtime.totalMemory() returns currently allocated memory only.Brainwash
E
18

Another way (currently showing 25MB free on my G1):

MemoryInfo mi = new MemoryInfo();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 1048576L;
Ethben answered 3/7, 2010 at 14:14 Comment(2)
Hey Alex, Thanks a lot for your help ! 1 more question. This code gives me available RAM. I also want to display Total RAM. How to get that?Inhaler
@Inhaler I don't know a Java API for that. Stick to parsing /proc/meminfo.Ethben
H
14

Linux's memory management philosophy is "Free memory is wasted memory".

I assume that the next two lines will show how much memory is in "Buffers" and how much is "Cached". While there is a difference between the two (please don't ask what that difference is :) they both roughly add up to the amount of memory used to cache file data and metadata.

A far more useful guide to free memory on a Linux system is the free(1) command; on my desktop, it reports information like this:

$ free -m
             total       used       free     shared    buffers     cached
Mem:          5980       1055       4924          0         91        374
-/+ buffers/cache:        589       5391
Swap:         6347          0       6347

The +/- buffers/cache: line is the magic line, it reports that I've really got around 589 megs of actively required process memory, and around 5391 megs of 'free' memory, in the sense that the 91+374 megabytes of buffers/cached memory can be thrown away if the memory could be more profitably used elsewhere.

(My machine has been up for about three hours, doing nearly nothing but stackoverflow, which is why I have so much free memory.)

If Android doesn't ship with free(1), you can do the math yourself with the /proc/meminfo file; I just like the free(1) output format. :)

Hippodrome answered 3/7, 2010 at 7:44 Comment(1)
@Igor, then you'll want to cat /proc/meminfo instead. It's far more detailed, but MemFree. Buffers, and Cached are likely the most important lines.Hippodrome
F
7

I refer few writings.

reference:

This getMemorySize() method is returned MemorySize that has total and free memory size.
I don't believe this code perfectly.
This code is testing on 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;
    }

I know that Pattern.compile() is expensive cost so You may move its code to class member.

Flee answered 17/5, 2015 at 14:12 Comment(0)
G
4

I looked at Android Source Tree.

Inside com.android.server.am.ActivityManagerService.java (internal service exposed by 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);
}

Inside android.os.Process.java

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

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

It calls JNI method from android_util_Process.cpp

Conclusion

MemoryInfo.availMem = MemFree + Cached in /proc/meminfo.

Notes

Total Memory is added in API level 16.

Gerick answered 19/9, 2013 at 11:59 Comment(0)
S
3
/** accurate value under limitation */
int getAccurateAppUsedMemory() {
    ActivityManager manager = context.getSystemService(Context.ACTIVITY_SERVICE);
    Debug.MemoryInfo info = manager.getProcessMemoryInfo(new int[]{Process.myPid()})[0];
    // Warning: there's a limitation of invocation frequency on Android Q or later
    return info.getTotalPss(); // in kB
}

/** approximate value without limitation */
int getApproximateAppUsedMemory() {
    Debug.MemoryInfo info = new Debug.MemoryInfo();
    Debug.getMemoryInfo(info);
    return info.getTotalPss(); // in kB
}
Sauropod answered 29/5, 2023 at 6:4 Comment(0)
Y
1

you can also use DDMS tool which is part of android SDK it self. it helps in getting memory allocations of java code and native c/c++ code as well.

Yestreen answered 15/3, 2013 at 10:12 Comment(0)
G
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;
}
Grand answered 15/9, 2017 at 14:3 Comment(0)
S
0
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

It is a strange code. It return MaxMemory - (totalMemory - freeMemory). If freeMemory equals 0, then the code will return MaxMemory - totalMemory, so it can more or equals 0. Why freeMemory not used?

Scarabaeus answered 17/4, 2019 at 7:39 Comment(0)
G
0

Here is another way to view your app's memory usage:

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

Sample output:

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

For overall memory usage:

adb shell dumpsys meminfo

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

Grekin answered 11/6, 2020 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.