Android: how to check how much memory is remaining?
Asked Answered
Y

2

30

Below is my formula to check how much memory is remaining (not how much memory remains in the current heap, but how much more memory may be utilized before the application crashes). I'm not remotely sure this is correct, is it?

double max = Runtime.getRuntime().maxMemory(); //the maximum memory the app can use
double heapSize = Runtime.getRuntime().totalMemory(); //current heap size
double heapRemaining = Runtime.getRuntime().freeMemory(); //amount available in heap
double nativeUsage = Debug.getNativeHeapAllocatedSize(); //is this right? I only want to account for native memory that my app is being "charged" for.  Is this the proper way to account for that?

//heapSize - heapRemaining = heapUsed + nativeUsage = totalUsage
double remaining = max - (heapSize - heapRemaininng + nativeUsage); 
Yulan answered 20/5, 2011 at 14:54 Comment(4)
Am I misunderstanding something? Why is getNativeHeapFreeSize() goo.gl/wsBKT not what you wanted?Belden
The difference between maxMemory() and heapSize() is the amount of memory that you can be pretty sure is available for a large contiguous allocation. The additional amount indicated by freeMemory() is the presently-unallocated amount within the present heap, which means that some part of that amount is probably fragmented, the amount of which would depend upon the increment used to grow the heap when required, and how much of that increment has already been used and then returned. So using your number "remaining" above may be risky if you need additional memory in a contiguous chunk.Natica
I would add that rather than dynamically testing to see how much memory is available, testing a number of extreme use cases during development for a variety of maxMemory() values and making sure that your app can handle them could be a better approach. Because if you discover at a certain point that you're getting close to your memory limits, it may be hard to back out of whatever you are doing in a way that's not rude to the user.Natica
Just a general observation: you're assigning longs to double variables, that's probably not a good idea.Diley
A
22

Try the following code. that should give you the results you are after (especially the Pss field). You can read more about it here

Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo();
Debug.getMemoryInfo(memoryInfo);

String memMessage = String.format(
    "Memory: Pss=%.2f MB, Private=%.2f MB, Shared=%.2f MB",
    memoryInfo.getTotalPss() / 1024.0,
    memoryInfo.getTotalPrivateDirty() / 1024.0,
    memoryInfo.getTotalSharedDirty() / 1024.0);
Alveolate answered 27/5, 2011 at 12:30 Comment(6)
Thank you! So, my interpretation of the article is that I can calculate currently available memory as: Runtime.getRuntime().maxMemory() - memoryInfo.getTotalPss()? Does that seem accurate and safe to you?Yulan
Looks good to me (haven't tried it though...). on the other hand, it could be that the maxMemory is also considering the shared memory since this is the maximum that can be allocated by the VM. so I'd look for more info about it...Alveolate
I marked as answered because it was helpful, but really this did not appear to be a reliable way to measure memory. What I would like, is for a method that gives the amount of native memory for which my application is being charged, which in most cases should be the amount of memory allocated for bitmaps. getTotalPss() does not seem to return this accurately, at all. This is my final solution to the issue, thought its not great: #6205996Yulan
@Yulan It seems that bitmap allocations are computed in the heap, take a look at: https://mcmap.net/q/27159/-bitmaps-in-android/…Revenue
@Mr. Roland, I'm not sure if I read that properly, this is my interpretation: prior to 3.0, bitmap allocations are counted against the heap limit, but do not show in the davlik heap. After 3.0, the allocations are actually in the davlik heap?Yulan
Why the division by 1024? Acording to Android Docs the results are in kB (multiple of 1000) and NOT in KB or KIB. developer.android.com/reference/android/os/… en.wikipedia.org/wiki/KilobyteBicapsular
F
4

This is an old thread, but this seems to work:

  Runtime.getRuntime().gc();
  long memoryAvailable = (Runtime.getRuntime().maxMemory() -
        Runtime.getRuntime().totalMemory() +
        Runtime.getRuntime().freeMemory());

totalMemory-freeMemory is the current used memory.

So this boils down to:

(maximum possible memory)-(current used memory)

Edit to add: freeMemory does not count memory available for garbage collection, so you can try Runtime.getRuntime().gc(), although realize that can have its own consequences (like visual hiccups if run on the UI thread).

Future answered 29/12, 2016 at 5:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.