Android Memory Management FIX THIS TITLE>

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]