48
Memory Management Fundamentals for Android apps

Android memory fundamentals

Embed Size (px)

DESCRIPTION

Presentation for GDG Workshop, 3 April 2013. A few words about memory management in Android Applications.

Citation preview

Page 1: Android memory fundamentals

Memory  Management  Fundamentals  for  Android  apps  

Page 2: Android memory fundamentals

Agenda  

1.  Memory  usage  model  – Constraints    – Zygote,  Dalvik  and  GC  

2.  Tools  for  memory  diagnos@cs  –  adb  shell  procrank  –  lava.lang.Run@me  –  Log  messages  –  Alloca@on  tracker  –  Eclipse  MAT  

     

Page 3: Android memory fundamentals

T-­‐Mobile  G1  (2008)  

192  MB  Nexus  4  (2012)  

2  GB  

We’ve  grown  bigger  and  stronger  

12x  RAM    

Page 4: Android memory fundamentals

So  why  should  we  care  about  the  memory?  

•  Heap  size  is  limited  and  device  dependent  •  Screen  size  has  grown  drama@cally  -­‐  Bitmaps  •  System  libraries  occupy  significant  amount  of  storage  

•  The  more  memory  we  use,  the  more  work  GC  has,  the  more  work  GC  has  the  bigger  pause  @me  will  be.  

•  BaWery  life  

Page 5: Android memory fundamentals

Dalvik  VM  

Page 6: Android memory fundamentals

Dalvik  VM  .dex  format  

Page 7: Android memory fundamentals

Respect  the  balance!  Cache  as  

much  useful  data  as  you  

can  

Use  as  liWle  memory  as  you  can  

Why?  

I  will  kill  your  process  as  soon  as  I  don’t  have  

memory  for  other  apps  and  your  app  uses  lots  of  

memory  

Why?  

I  can  do  mul@tasking  and  I  want  smooth  UX  when  switching  between  apps  

Page 8: Android memory fundamentals

Mark-­‐and-­‐sweep  GC  

Larger  heap  =  larger  pause  @me  =  poor  performance  

Page 9: Android memory fundamentals

Mark-­‐and-­‐sweep  GC  

Phase  1  Before  GC  

GC  Roots  

Page 10: Android memory fundamentals

Mark-­‐and-­‐sweep  GC  

GC  Roots  Phase  2  

Marking  complete    

-­‐  Marked  object  

Mark:  star@ng  from  roots,  mark  all  reachable  objects  by  using  a  depth-­‐first-­‐search  pointer  traversal  

-­‐  Garbage  

Page 11: Android memory fundamentals

Mark-­‐and-­‐sweep  GC  

GC  Roots  Phase  3  

Sweep  complete    

-­‐  Marked  object  

Sweep:  scan  the  heap  from  the  beginning  to  the  end  and  reclaim  the  unmarked  objects  (and  unmark  the  marked  objects).  

Page 12: Android memory fundamentals

GC  Improvements  

Before   Aber  Garbage  collector  

•  Advantage  of  mul@core  support  •  Mostly  concurrent  •  Par@al  collec@ons  •  Smaller  pause  @mes  

•  Stop-­‐the-­‐world  •  Full  heap  collec@on  •  Large  pause  @mes  

Page 13: Android memory fundamentals

GC  Improvements  Before   Aber  

•  Stop-­‐the-­‐world  –  all  app  threads  are  stopped  

•  Full  heap  collec@on  •  Large  pause  @mes  

oben  >  100ms  

•  Ini4al  mark  -­‐  stop-­‐the-­‐world  •  Mark  -­‐  concurrent  •  Remark  –  stop-­‐the-­‐world  •  Sweep  -­‐  concurrent  

Page 14: Android memory fundamentals

Healthy  memory  usage  paWern  

Time  

Allocated    memory  

Maximum  heap*  size  

GC  Run  

Memory  Usage  

Garbage  

*  Maximum  amount  of  memory  our  app  is  allowed  to  use  

Page 15: Android memory fundamentals

Edge  case  

Time  

Allocated    memory  

Maximum  heap*  size  

Memory  Usage  

Garbage  

GC  Run  

OutOfMemoryError  

*  Maximum  amount  of  memory  our  app  is  allowed  to  use  

Page 16: Android memory fundamentals

Are  we  leaking  memory?  

Time  

Allocated    memory  

Maximum  heap*  size  

Memory  Usage  

Garbage  

GC  Run  

Amount  of  memory  leaking  

Memory  leak  *  Maximum  amount  of  memory  our  app  is  allowed  to  use  

Page 17: Android memory fundamentals

Maximum  heap  size  So  how  much  memory  can  we  actually  use?  

 1.  ActivityManager.getMemoryClass()  –    device  dependent  –  always  constant  2.  Runtime.getRuntime().maxMemory()  –    can  be  changed  on  rooted  devices,  is  slightly  larger      

 

T-­‐Mobile  G1  –  16  MB   Nexus  One  –  32  MB   Nexus  7  –  64  MB    

Page 18: Android memory fundamentals

Memory  intensive  apps  

What  if  it  is  not  enough?  Image  editor?  Video  editor?  3D  game?    <application  

 android:largeHeap=“true”  </application>    

Use  only  if  you  are  sure  you  need  this  extra  memory.    ActivityManager.getLargeMemoryClass()  

   

Page 19: Android memory fundamentals

We  are  armed  

Page 20: Android memory fundamentals

Target  –  Honeycomb  Gallery  App  

YOUR_SDK_LOCATION\samples\android-­‐XX\HoneycombGallery  

Page 21: Android memory fundamentals

Tools  to  diagnose  memory  usage  

1.  adb  shell  procrank  2.  java.lang.Run@me  3.  Log  messages  4.  Alloca@on  tracker  and  heap  updates  5.   Heap  dumps  and  Eclipse  Memory  Analyzer  

Tool  (MAT)  

Page 22: Android memory fundamentals

procrank  u@lity  

Applica4on:  answers  a  ques@on  how  much  memory  are  we  actually  using.  

Page 23: Android memory fundamentals

procrank  

Lists  of  all  processes  on  the  device  and  memory  they  are  using  (sorted  desc.).    adb  shell  procrank  (requires  root  access)    Uss  –  Unique  set  size  –  rough  memory  amount  the  system  would  reclaim  if  it  kills  the  process.  

Page 24: Android memory fundamentals

Java.lang.Run@me  methods  

•  freeMemory()  •  totalMemory()  

Applica4on:    •  observing  general  applica@on  memory  usage  

paWern  at  run@me  •  provides  basic  understanding  of  memory  usage  

behavior  

Page 25: Android memory fundamentals

             Observing  memory  state  changes  in  LogCat  

new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(5000); } catch (InterruptedException e) { // do nothing } reportMemoryUsage(); } } }, “MemoryUsageReporter").start();  

Page 26: Android memory fundamentals

 Gives  a  general  idea  about  memory  

changes  at  run@me  RAM  USAGE  free:  1.96MB,  total:  14.68MB,  max  :  64.00  RAM  USAGE  free:  1.95MB,  total:  14.68MB,  max  :  64.00  RAM  USAGE  free:  1.71MB,  total:  14.68MB,  max  :  64.00  RAM  USAGE  free:  1.71MB,  total:  14.68MB,  max  :  64.00  RAM  USAGE  free:  4.62MB,  total:  17.35MB,  max  :  64.00  RAM  USAGE  free:  4.62MB,  total:  17.35MB,  max  :  64.00  RAM  USAGE  free:  1.95MB,  total:  14.68MB,  max  :  64.00  RAM  USAGE  free:  1.95MB,  total:  14.68MB,  max  :  64.00  RAM  USAGE  free:  1.95MB,  total:  14.68MB,  max  :  64.00    

Page 27: Android memory fundamentals

Interpre@ng  LogCat  messages  

02-­‐25  11:12:59.321:  D/dalvikvm(7757):  GC_CONCURRENT  freed  1536K,  17%  free  10790K/12856K,  paused  3ms+3ms,  total  21ms  

Page 28: Android memory fundamentals

General  informa@on  

•  Timestamp  •  Logging  level  •  Log  tag  •  Process  id  

02-­‐25  11:12:59.321:  D/dalvikvm(7757):  GC_CONCURRENT  freed  1536K,  17%  free  10790K/12856K,  paused  3ms+3ms,  total  21ms  

Page 29: Android memory fundamentals

Reason  for  GC  Run  

Possible  reasons:  •  GC_CONCURRENT  •  GC_FOR_MALLOC/GC_FOR_ALLOC  •  GC_EXTERNAL_ALLOC  •  GC_HPROF_DUMP_HEAP  •  GC_EXPLICIT  

02-­‐25  11:12:59.321:  D/dalvikvm(7757):  GC_CONCURRENT  freed  1536K,  17%  free  10790K/12856K,  paused  3ms+3ms,  total  21ms  

GC_CONCURRENT  

Page 30: Android memory fundamentals

                         Amount  of  memory  reclaimed  02-­‐25  11:12:59.321:  D/dalvikvm(7757):  GC_CONCURRENT  freed  1536K,  17%  free  10790K/12856K,  paused  3ms+3ms,  total  21ms  

freed  1536K,    

Heap  sta@s@cs     02-­‐25  11:12:59.321:  D/dalvikvm(7757):  GC_CONCURRENT  freed  1536K,  17%  free  10790K/12856K,  paused  3ms+3ms,  total  21ms  17%  free  10790K/12856K  

•  Percentage  of  free  heap  memory  aber  the  GC  run  •  Size  of  objects  alive/Total  heap  size    

Pause  @me     02-­‐25  11:12:59.321:  D/dalvikvm(7757):  GC_CONCURRENT  freed  1536K,  17%  free  10790K/12856K,  paused  3ms+3ms,  total  21ms  paused  3ms+3ms,  total  21ms  

Page 31: Android memory fundamentals

Bitmaps  –  what  has  changed?  Before  Honeycomb  

Dalvik  Heap  

Na@ve  Memory  

Pixel  Data  

Page 32: Android memory fundamentals

Bitmaps  –  what  has  changed?  Aber  Honeycomb  

Dalvik  Heap  

Na@ve  Memory  

Pixel  Data  

Page 33: Android memory fundamentals

Bitmaps  –  what  has  changed?  

Before   Aber  

Bitmap  pixel  data  storage  

Na@ve  memory  •  Freed  via  –recycle  or  finalizer  •  Hard  to  debug  •  Full  GC  (stop-­‐the-­‐world)  

Dalvik  Heap  •  Freed  synchronously  by  GC  •  Easy  to  debug  •  Concurrent  and  par@al  GCs  

Page 34: Android memory fundamentals

Profit?  

• When  pixel  data  is  stored  in  Dalvik  heap  it  is  much  easier  to  debug  memory  usage  as  everything  is  in  one  place  •  Pixel  data  in  pre-­‐Honeycomb  was  freed  by  recycle()  or  finalizer,  now  freed  syncronously  by  GC  •  GCs  of  pixel  data  are  now  concurrent  and  par4al  –  pause  4mes  are  smaller  

Page 35: Android memory fundamentals

Alloca@on  tracker  (Monitor)  

•  Info  about    object  alloca@ons  in  a  specific  @me  period    

Page 36: Android memory fundamentals

Eclipse  Memory  Analyzer  Tool  

Page 37: Android memory fundamentals

Heap  Dump  

•  Is  a  snapshot  of  all  “living”  objects  at  a  given  point  in  @me  

•  Contains  info  about  which  objects  are  GC  roots  (will  not  be  reclaimed  if  there  are  no  refs  to  them).  

•  Does  not  contain  info  about  na@ve  objects  (pre-­‐Honeycomb  Bitmaps  e.g.)  

Page 38: Android memory fundamentals

Object  size  

•  Shallow  size  of  an  object  –  amount  of  memory  allocated  to  store  the  object  itself,  not  taking  into  account  the  referenced  object.  (Sum  of  size  of  the  object  header  and  the  fields)  

String  1   String  2  

Shallow  size  

Page 39: Android memory fundamentals

Shallow  object  size  -­‐  example  public  final  class  String  {  //  8  Bytes  header  

 private  char  value[];    //  4  Bytes    private  int  offset;  //  4  Bytes    private  int  count;  //  4  Bytes    private  int  hash  =  0;  //  4  Bytes  

…}    “Shallow  size”  of  a  String  ==  24  Bytes  (32  bit  Sun  JDK)    

Page 40: Android memory fundamentals

Retained  set  

•  Retained  set  of  object  X  –  The  set  of  objects  that  would  be  

garbage  collected,  if  object  X  is  deleted  

–  The  retained  size  of  an  object  X  is  equal  to  the  shallow  size  of  the  “Retained  sets”  of  X  

Object  X  

Retained  set  of  X  

Page 41: Android memory fundamentals

Genera@ng  a  heap  dump  file  

•  Dump  HPROF  file  (DDMS  or  programma@cally)*  •  Convert    (Not  needed  in  Eclipse  DDMS)  hprof-­‐conv  dump.hprof  dump-­‐conv.hprof  •  Open  the  file  with  Eclipse  MAT  

*android.os.dumpHprofData(String  filename)  

Page 42: Android memory fundamentals

Ini@al  pie  chart  view  

•  Shows  the  biggest  objects  be  their  retained  size  

Page 43: Android memory fundamentals

Histogram  view  Number  of  instances  of  each  class  and  their  shallow  size  

Page 44: Android memory fundamentals

Histogram  view  Oben  not  very  useful.  Why?  

Class  name   Number  of  objects   Shallow  size  in  bytes  

char[]   9  597   555  496  

Java.lang.String   10  799   259  176  

How  many  char[]  are  caused  by  String  instances?  

Page 45: Android memory fundamentals

Dominator  tree  example  

An  object  A  dominates  on  an  object  B  if  all  the  paths  to  object  B  pass  through  object  A.  

1.  Note  that  A,  B  and  C  are  dominated  by  a  "virtual"  root  object.    2.  Note  that  the  dominator  rela@onship  is  transi4ve;  C  dominates  E  which  dominates  G  therefore  C  also  dominates  G.  

Page 46: Android memory fundamentals

Dominator  tree  view  List  of  objects  by  their  retained  heap  

Page 47: Android memory fundamentals

Memory  Leak  Demo  

Page 48: Android memory fundamentals

Ques@ons?  

Taras  Leskiv  [email protected]  linkedin.com/in/tarasleskiv