Contents

System Memory

You can examine the system's view of the memory on the machine, by examining /proc/meminfo.

If you use 'ddms', you can see a summary of the memory used on the machine, by the system and
by the different executing processes. Click on the SysInfo tab, and select "Memory Usage" in the
box on the upper left of the pane.

Here's a screenshot:

Note that you can get the numbers for each process by hovering your mouse over a particular pie slice.
Numbers are shown in K and percentages.

Process Memory

You can see an individual process' memory usage by examining /proc/<pid>/status

Details about memory usage are in

/proc/<pid>/statm

/proc/<pid>/maps

/proc/<pid>/smaps

The 'top' command will show VSS and RSS.

Also, see ddms info above.

procrank

procrank will show you a quick summary of process memory utilization. By default, it shows
Vss, Rss, Pss and Uss, and sorts by Vss. However, you can control the sorting order.

procrank source is included in system/extras/procrank, and the binary is located in /system/xbin
on an android device.

Vss = virtual set size

Rss = resident set size

Pss = proportional set size

Uss = unique set size

In general, the two numbers you want to watch are the Pss and Uss (Vss and Rss are generally
worthless, because they don't accurately reflect a process's usage of pages shared with other
processes.)

Uss is the set of pages that are unique to a process. This is the amount of memory that would be freed if the application was terminated right now.

Pss is the amount of memory shared with other processes, accounted in a way that the amount is divided evenly between the processes that share it. This is memory that would not be released if the process was terminated, but is indicative of the amount that this process is "contributing"

to the overall memory load.

You can also use procrank to view the working set size of each process, and to reset the working
set size counters.

In this example, it shows that the native daemons and programs are an order of magnitude smaller
than the Dalvik-based services and programs. Also, even the smallest Dalvik program requires
about 1.5 meg (Uss) to run.

smem tool

You can see very detailed per-process or systemwide memory information with smem.

Dalvik Heap

The Dalvik heap is preloaded with classes and data by zygote (loading over 1900 classes as of Android version 2.2). When zygote forks to start an android application, the new application gets a copy-on-write mapping of this heap. As Dan Borstein says below, this helps with memory reduction as well as application startup time.

Dalvik, like virtual machines for many other languages, does garbage collection on the heap. There appears to be a separate thread (called the HeapWorker) in each VM process that performs the garbage collection actions. (See toolbox ps -t) [need more notes on the garbage collection]

It's used in Android to amortize the RAM footprint of the large amount of effectively-read-only data (technically writable but rarely actually written) associated with common library classes across all active VM processes. 1000+ classes get preloaded by the system at boot time, and each class consumes at least a little heap for itself, including often pointing off to a constellation of other objects. The heap created by the preloading process gets shared copy-on-write with each spawned VM process (but again doesn't in practice get written much). This saves hundreds of kB of dirty unpageable RAM per process and also helps speed up process startup.

How to debug native process memory allocations

libc.debug.malloc

The C library in the system supports the ability to utilize a different, debug, version of the malloc code at runtime in the system.

If the system property libc.debug.malloc has a value other than 0, then when a process is instantiated, the C library uses
functions for allocating and freeing memory, for that process.

(Note that there are other ways that the debug shared library malloc code ends up being used as well.
That is, if you are running in the emulator, and the value of the system property ro.kernel.memcheck is not '0', then
you get a debug level of 20. Note that debug level 20 can only be used in the emulator.)

By default, the standard malloc/free/calloc/realloc/memalign routines are used. By setting libc.debug.malloc,
different routines are used, which check for certain kinds of memory errors (such as leaks and overruns). This is done
by loading a separate shared library (.so) with these different routines.

The shared libraries are named: /system/lib/libc_malloc_debug_leak.so and /system/lib/libc_malloc_debug_qemu.so

(Information was obtained by looking at <android-source-root>/bionic/libc/bionic/malloc_debug_common.c)