Android: Managing
Memory
Russell Myers
Me
Russell Myers
Amazon
Fire Phone
Middleware – applications
and components
Web (recent)
Intranet sites for Comcast,
Verizon, etc.
Overview
How much do we have?
It’s been bad (Google I/O 2011 Memory Management For Android Applications)
G1 (first Android phone): 16 MB
Droid: 24 MB
Nexus One: 32 MB
Xoom (first “real” Android tablet): 48 MB
These days
512 MB – 2 GB (reasonable targets)
Android “L” will likely see an increase in this as 64-bit devices come in.
KitKat could invite more low end devices as well.
By the way, no memory swapping!
Is it really that much? (hint: No)
From my Nexus 7 (2013) (all numbers in PSS)
adb shell dumpsys meminfo
System “stuff”
126350 kB: com.google.android.googlequicksearchbox
75594 kB: surfaceflinger
46574 kB: com.android.systemui
45217 kB: system
45054 kB: com.google.android.inputmethod.latin
13073 kB: com.google.process.location
12074 kB: zygote
9011 kB: com.android.phone (really!?)
Other apps
68521 kB: com.facebook.katana
36805 kB: com.amazon.kindle
85455 kB: com.android.chrome
…
The bigger they are, the faster they fall.
Low-Memory Killer (LMK) (http://lwn.net/Articles/317814/)
Kills applications before the device runs out of memory; not when.
“Androidism”
Threshold heuristics
Recency
Size
Priority
Can be different per device.
Tablets are worse
Pushing more pixels
Nexus 5: 1920 x 1080
Fire Phone: 1280 x 720
Nexus 7 (2013): 1920 x 1200
Kindle Fire HDX 7: 1920 x 1200
Kindle Fire HDX 8.9: 2560 x 1600
ARGB_8888
Fire Phone - ~3.5 MB
Kindle Fire HDX 8.9: ~15.6 MB
More views or bigger views
More advanced interfaces
Ramifications
Crashes
Out of memory exceptions
Can’t free memory fast enough, causing ANRS
Application terminated more frequently in background
Restarts (thus slower starts) more often.
Potential loss of state
Can cause these problems for other applications as well!
More power consumption
Ramifications (continued)
More GC invocations!
GC invocations get logged to logcat:
Example: D/Dalvikvm GC_EXPLICIT freed 1328K 35 free 26195 39879K
paused 3ms 5ms total 122ms
There are a few types of garbage collection:
GC_CONCURRENT - Happens every so often based on Android's perception
of heap size. Some aspects of this are concurrent, but not all.
GC_FOR_ALLOC - Happens when GC_CONCURRENT either couldn't free
enough space in time for an allocation, or the allocation exceeded
expectations.
GC_BEFORE_OOM - A more aggressive GC call that happens right before a
memory error. This occurs if GC_FOR_ALLOC fails.
GC_EXPLICIT - Explicit GC call. (if you want this control, go unmanaged)
Looking at memory
Quick look
adb shell dumpsys meminfo <package name>
Shared – Shared memory
Private – Stuff that’s just yours or “yet to be shared”.
RSS – Resident Set Size
PSS – Proportional Set Size
Activities
Views
Memory leaks
A leak is a situation in which you have unexpected growth. A
leak can be bounded or unbounded. You care about both!
Bounded being “after a lot of use X grows to 300 MB but stays
there”.
Unbounded being “things continue to grow and grow”
Rate of leak matters
How does the leak occur?
Usage pattern
Background interaction
Potential causes
Context leaks
Activities
Views
Bitmap leaks
Singleton references
Listeners
Observers
Async operations (runnables, handlers, threads)
Inner classes hold references to parent classes
Testing for memory leaks
watch --interval=2.0 “adb shell dumpsys meminfo
<package name>”
Acceptance tests / automated UI tests that run through
common interactions.
Espresso
Monkeyrunner
Note the seeds used in case you need to reproduce!
Not smart, but randomized.
Testing (continued)
Understand the lifecycle of components of your application.
Activities / Views shouldn’t hang around.
Done with that Bitmap?
When does that listener need to be deregistered?
Make sure you’re actually cleaning up in a safe area.
(Activity#onStop() may not be called for example!)
Cache only what you absolutely need!
There will be growth!
GC doesn’t constantly run (that’d be very bad)
Overhead should (hopefully) remain low.
Found a leak!
Root causing. What’s leaking?
Eclipse MAT
Activities, Views, Contexts, “managed stuff”
NDK for unmanaged
Embedded into Eclipse
Update site: http://download.eclipse.org/mat/1.3.1/update-site/
No conversions necessary. (hprof-conv)
Stand-alone tool
http://www.eclipse.org/mat/downloads.php
NDK for unmanaged stuff
Using MAT
Open hprof files.
Interesting views
Histogram
Dominator Tree
Top consumers
Comparing two hprofs from Histogram
Still using MAT
• Weak references don’t prevent garbage collection.
• Shallow heap – Object size in bytes.
• Retained heap – Size objects that could be freed by freeing the
object.
• Considers other references
/proc/[pid]/smaps
smaps ()
{
pid=$(adb shell ps | grep "$1" | awk '{print $2}');
adb shell cat /proc/$pid/smaps | tr -d '\r’ # Parsing problems
}
“This file shows memory consumption for each of the process’s mappings”
(proc man page)
Useful for non-heap items (and in some situations when the NDK can’t help)
There’s a lot of other fun stuff in /proc by the way. Check it out.
Estimation
What are you going to take up in the worst case?
What does a “worst case” even mean?
How does your application grow?
Notes app – Number of notes, size of notes, extra details to note,
number of points in time notes occurred, etc.
Books library – Number of books, covers of a book, book content,
different in-memory caches of books.
Game – Textures, models, players, monsters, pieces, etc.
Measure costs along different points in that growth pattern to
get an estimation and understand impact of different
dimensions of growth.
Supported devices (and as a result, image sizes)
Good link
http://developer.android.com/training/articles/memory.html
Thanks!
Twitter: @russell_myers
E-mail: [email protected]
© Copyright 2025 Paperzz