Measuring memory usage on a device

1,674 views
Skip to first unread message

Magnus

unread,
Mar 20, 2009, 10:18:59 AM3/20/09
to android-porting
Hi,

I was wondering about the best way to measure the remaining RAM on a
device. I have jusrt been using the emulator so far, and I connected
to the emulator using the "adb shell" command to get a Linux prompt
and used the vmstat command, in good old UNIX fashion, and got the
followoing output:

r b free mapped anon slab in cs flt us ni sy id wa ir
0 0 42236 21820 30700 3176 52 10 0 1 0 0 99 0 0


which I would interpret as 42236 kB of free RAM.

Then I tried to check this via a Java program and used the
MemoryInfo.availMem function as follows:

mgr = (ActivityManager) super.getSystemService
(Context.ACTIVITY_SERVICE);
memInfo = new ActivityManager.MemoryInfo();
mgr.getMemoryInfo(memInfo);
s = String.valueOf(memInfo.availMem);

and get a completely different result, it gives me about 88 MB
(88965120).

Which is the correct amount of remaining RAM in the device?

Thanks,

-Magnus

Dianne Hackborn

unread,
Mar 20, 2009, 5:15:41 PM3/20/09
to android...@googlegroups.com
You really can't.

You can look in /proc/meminfo for the kernel's numbers.  "MemFree" and "Cached" are the most useful ones there, which together give an indication how much could possibly be free...  but ideally MemFree is small, and Cached is in use but some part of it can actually be used for other things if needed, but how much of that actually can is not going to be clear -- basically as it gets smaller, things will start running more slowly as more paging happens, but exactly when and where that starts impacting things enough that you care...  well.

On top of that, Android tries to keep as many application processes running as it can, even though they may not be absolutely needed.  So you will see the system consistently having a lot of memory really in use, but in fact if there are memory demands from more important processes, the less important ones can be killed to reclaim memory for them.

So all of this information is somewhat useful for trying to debug the overall behavior of the system, but really not useful for applications.  The main thing we have is the onLowMemory() callback, to tell applications to free memory if they can.  This is called when the system detects that all of the extraneous background processes have been killed, and it would really like to have some memory freed up before more important processes need to be terminated.

--
Dianne Hackborn
Android framework engineer
hac...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support.  All such questions should be posted on public forums, where I and others can see and answer them.

Magnus

unread,
Mar 23, 2009, 9:25:07 AM3/23/09
to android-porting
Hi,

I was trying to understand/estimate how much memory that is reasonable
to have in a device running Android.

When booting up the system fresh you can see in the emulator that if I
configure the emulator to have 64MB RAM (emulator -qemu -m 64)
available it gives you an available RAM of a few MB, whereas if you
configure the emulator to have 128 MB of RAM it seems to give you just
over 40 MB free aftoot, indicating that the system uses about 80 MB of
RAM after boot. How does this work in the 64MB RAM case, does the
system not start some services or does it use paging to fit into the
small RAM?

I can't seem to locate any good descriptions on how Android works on
this lower level.

Thanks,

-Magnus

Dianne Hackborn

unread,
Mar 23, 2009, 1:28:43 PM3/23/09
to android...@googlegroups.com
The available RAM is pretty meaningless.  I wouldn't suggest using 64MB at this point.  You might want to target 128MB but this all really depends -- the G1 has 192MB, but 40MB of that is used by the radio image, another bunch is not available to Linux but does get used for surfaces and other buffers, and we have about 90MB available to Linux.  So if there is truly 128MB available to Linux, you are probably in decent shape -- that is similar to the G1, especially if you are putting surfaces and other buffers in that 128MB.

Anyway, the kernel is set up to do demand paging, so mostly what you will see when memory is tight is a lot of paging and/or the platform unable to keep any background processes running (or even killing service processes), which also makes things slow.

James Whetstone

unread,
Mar 23, 2009, 3:35:20 PM3/23/09
to android...@googlegroups.com
Hi,
 
I'm porting android to the Davinci board and I'm using the open source Linux kernel that Kevin Hilman is working on.  It's version 2.6.29 rc8.  Has anyone ported Android to this Linux kernel?   I'm confused about what the best way to go about taking the Android kernel, version 2.6.25, and applying the changes my Davinci linux version 2.6.29.  Can anyone help me out with this?
 
---Jim

Magnus

unread,
Apr 21, 2009, 5:21:09 AM4/21/09
to android-porting
Thanks.

I would still like to get an explanation as to why the Java APIs show
a lot more memory available than the UNIX commands available in the
adb shell.

memInfo = new ActivityManager.MemoryInfo();
mgr.getMemoryInfo(memInfo);
s = String.valueOf(memInfo.availMem);

Is the Dalvik machine allocating memory at start that is not available
to the Linux kernel but shown form the Java APIs?
Or is it something about those buffers etc. that Diane mentions above
that are not shown as available to Linux?

This has been puzzling me for quite some time now ...

Thanks,

-Magnus
> hack...@android.com
>
> Note: please don't send private questions to me, as I don't have time to
> provide private support.  All such questions should be posted on public
> forums, where I and others can see and answer them.- Hide quoted text -
>
> - Show quoted text -

fadden

unread,
Apr 22, 2009, 1:13:43 PM4/22/09
to android-porting
On Apr 21, 2:21 am, Magnus <perssonmag...@gmail.com> wrote:
> I would still like to get an explanation as to why the Java APIs show
> a lot more memory available than the UNIX commands available in the
> adb shell.
>
> memInfo = new ActivityManager.MemoryInfo();
>         mgr.getMemoryInfo(memInfo);
>         s = String.valueOf(memInfo.availMem);
>
> Is the Dalvik machine allocating memory at start that is not available
> to the Linux kernel but shown form the Java APIs?

ActivityManager.MemoryInfo is not related to Dalvik. Note this is
different from Debug.MemoryInfo (which is also largely unrelated to
the VM).

ActivityManager.MemoryInfo uses ActivityManager.getMemoryInfo (see
frameworks/base/core/java/android/app/ActivityManager.java). The call
into the system service ends up in
ActivityManagerService.getMemoryInfo (frameworks/base/services/java/
com/android/server/am/ActivityManagerService.java).

public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
outInfo.availMem = Process.getFreeMemory();
outInfo.threshold = HOME_APP_MEM;
outInfo.lowMemory = outInfo.availMem <
(HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
}

Process.getFreeMemory is implemented in frameworks/base/core/jni/
android_util_Process.cpp. It opens /proc/meminfo and adds up MemFree
and Cached.

FWIW, I don't believe I've looked at any of this code before. All I
did was grep for strings in your original message, look at the
sources, and iterate. There's no need to remain puzzled when
recursive grep is available. :-) (If you ". build/envsetup.sh" in the
source tree, you will have a handy "sgrep" shell command. The first
one takes a while to run if you do it over the entire source tree, but
after that it's all in the disk cache and you can grep the entire
thing quickly -- 1.75 seconds on my system.)
Reply all
Reply to author
Forward
0 new messages