Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android Performance Tips

237be48129b762b31847d6167597366d?s=47 Romain Guy
November 12, 2013

Android Performance Tips

This presentation explains in detail some of the performance improvements provided by Android 4.4. You will also learn about tools and tips you can use to improve performance of your applications.

237be48129b762b31847d6167597366d?s=128

Romain Guy

November 12, 2013
Tweet

Transcript

  1. Android Performance Tips Romain Guy Chet Haase google.com/+RomainGuy google.com/+ChetHaase @romainguy

    @chethaase
  2. Performance Improvements

  3. #DV13 #AndroidPerf Lazy Measurement • Introduced in Android 4.4 -

    targetSdkVersion must be >= 19 • Views cache measured dimensions - Prior to 4.4 only the last measure was cached - In 4.4 all measures are cached until next requestLayout() • Can greatly reduce calls to onMeasure()
  4. #DV13 #AndroidPerf Before 4.4 ViewGroup View View

  5. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec1, hSpec1)

  6. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec1, hSpec1) onMeasure(wSpec1,

    hSpec1)
  7. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec1, hSpec1) setDimensions(w1,

    h1) onMeasure(wSpec1, hSpec1)
  8. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec2, hSpec2)

  9. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec2, hSpec2) onMeasure(wSpec2,

    hSpec2)
  10. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec2, hSpec2) setDimensions(w2,

    h2) onMeasure(wSpec2, hSpec2)
  11. #DV13 #AndroidPerf Before 4.4 ViewGroup View View

  12. #DV13 #AndroidPerf Before 4.4 ViewGroup View View requestLayout()

  13. #DV13 #AndroidPerf Before 4.4 ViewGroup View View

  14. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec1, hSpec1)

  15. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec1, hSpec1) cached

    measure: (wSpec1, hSpec1) → (w1, h1)
  16. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec1, hSpec1) setDimensions(w1,

    h1) cached measure: (wSpec1, hSpec1) → (w1, h1)
  17. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec2, hSpec2)

  18. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec2, hSpec2) onMeasure(wSpec2,

    hSpec2)
  19. #DV13 #AndroidPerf Before 4.4 ViewGroup View View measure(wSpec2, hSpec2) setDimensions(w2,

    h2) onMeasure(wSpec2, hSpec2)
  20. #DV13 #AndroidPerf Single measure cache • Works great in common

    cases • Breaks with multi-pass layouts - LinearLayout and weight - RelativeLayout - Custom layouts
  21. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View

  22. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec1, hSpec1)

  23. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec1, hSpec1) onMeasure(wSpec1,

    hSpec1)
  24. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec1, hSpec1) setDimensions(w1,

    h1) onMeasure(wSpec1, hSpec1)
  25. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec2, hSpec2)

  26. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec2, hSpec2) onMeasure(wSpec2,

    hSpec2)
  27. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec2, hSpec2) setDimensions(w2,

    h2) onMeasure(wSpec2, hSpec2)
  28. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View

  29. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec3, hSpec3)

  30. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec3, hSpec3) onMeasure(wSpec3,

    hSpec3)
  31. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec3, hSpec3) setDimensions(w3,

    h3) onMeasure(wSpec3, hSpec3)
  32. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec4, hSpec4)

  33. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec4, hSpec4) onMeasure(wSpec4,

    hSpec4)
  34. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec4, hSpec4) setDimensions(w4,

    h4) onMeasure(wSpec4, hSpec4)
  35. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View

  36. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View requestLayout()

  37. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View

  38. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec1, hSpec1)

  39. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec1, hSpec1) cached

    measure: (wSpec3, hSpec3) → (w3, h3)
  40. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec1, hSpec1) onMeasure(wSpec3,

    hSpec3)
  41. #DV13 #AndroidPerf Multi-pass layout ViewGroup View View measure(wSpec1, hSpec1) setDimensions(w1,

    h1) onMeasure(wSpec3, hSpec3)
  42. #DV13 #AndroidPerf Multi-pass layouts • Siblings can cause extra onMeasure()

    calls • Nested multi-pass layouts can wreck havoc - A leaf View calling requestLayout() can relayout the entire tree! • Solution < 4.4 - Avoid multi-pass layouts - Use fewer Views • Solution >= 4.4 - Framework caches multiple measure pairs - Cache is cleared on requestLayout()
  43. #DV13 #AndroidPerf With 4.4 ViewGroup View View

  44. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec1, hSpec1)

  45. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec1, hSpec1) onMeasure(wSpec1,

    hSpec1)
  46. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec1, hSpec1) setDimensions(w1,

    h1) onMeasure(wSpec1, hSpec1)
  47. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec2, hSpec2)

  48. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec2, hSpec2) onMeasure(wSpec2,

    hSpec2)
  49. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec2, hSpec2) setDimensions(w2,

    h2) onMeasure(wSpec2, hSpec2)
  50. #DV13 #AndroidPerf With 4.4 ViewGroup View View

  51. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec3, hSpec3)

  52. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec3, hSpec3) onMeasure(wSpec3,

    hSpec3)
  53. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec3, hSpec3) setDimensions(w3,

    h3) onMeasure(wSpec3, hSpec3)
  54. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec4, hSpec4)

  55. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec4, hSpec4) onMeasure(wSpec4,

    hSpec4)
  56. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec4, hSpec4) setDimensions(w4,

    h4) onMeasure(wSpec4, hSpec4)
  57. #DV13 #AndroidPerf With 4.4 ViewGroup View View

  58. #DV13 #AndroidPerf With 4.4 ViewGroup View View requestLayout()

  59. #DV13 #AndroidPerf With 4.4 ViewGroup View View

  60. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec1, hSpec1)

  61. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec1, hSpec1) cached

    measures: (wSpec3, hSpec3) → (w3, h3) (wSpec1, hSpec1) → (w1, h1)
  62. #DV13 #AndroidPerf With 4.4 ViewGroup View View measure(wSpec1, hSpec1) setDimensions(w1,

    h1) cached measures: (wSpec3, hSpec3) → (w3, h3) (wSpec1, hSpec1) → (w1, h1)
  63. #DV13 #AndroidPerf Example RelativeLayout LinearLayout LinearLayout RelativeLayout Button TextView TextView

    TextView TextView RelativeLayout TextView TextView TextView
  64. #DV13 #AndroidPerf Example RelativeLayout LinearLayout LinearLayout RelativeLayout Button TextView TextView

    TextView TextView RelativeLayout TextView TextView TextView requestLayout()
  65. #DV13 #AndroidPerf Results targetSdk 18 19 measure time measure count

  66. #DV13 #AndroidPerf Results targetSdk 18 19 measure time measure count

    6.5ms 72
  67. #DV13 #AndroidPerf Results targetSdk 18 19 measure time measure count

    6.5ms 0.7ms 72 14
  68. #DV13 #AndroidPerf DisplayList Reordering and Merging • Batches similar commands

    • Minimizes state changes • Minimizes GL operations
  69. Save Cancel Maximize compatibility Include metadata

  70. None
  71. Include metadata Maximize compatibility Cancel Save Order of drawing commands

  72. Include metadata Maximize compatibility Cancel Save 1. Re-ordering

  73. Include metadata Maximize compatibility Cancel Save 2. Merging

  74. #DV13 #AndroidPerf

  75. #DV13 #AndroidPerf Without reordering & merging 48 draw calls

  76. #DV13 #AndroidPerf Without reordering & merging 48 draw calls With

    reordering & merging 18 draw calls
  77. #DV13 #AndroidPerf

  78. #DV13 #AndroidPerf Without reordering & merging 576 OpenGL driver calls

  79. #DV13 #AndroidPerf Without reordering & merging 576 OpenGL driver calls

    With reordering & merging 216 OpenGL driver calls
  80. #DV13 #AndroidPerf Asset Atlas

  81. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps
  82. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps Overdraw Window Background 1x
  83. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps Overdraw Container Background 2x
  84. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps Overdraw Button Button 2.1x Views
  85. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps
  86. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps Overdraw
  87. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps Overdraw Window Background 0x
  88. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps Overdraw Container Background 1x
  89. #DV13 #AndroidPerf Overdraw Removal • Detects coverage, areas hidden by

    opaque elements • Avoids drawing them • Eliminates some common overdraw situations • But you should still avoid it in your apps Overdraw Button Button 1.1x Views
  90. #DV13 #AndroidPerf Bitmap Reuse • Reuse in 3.0 required Bitmaps

    of same size/configuration • Bitmaps can now be reconfigured/resized - Can create scratch buffer and load smaller bitmaps into it
  91. Performance Tools

  92. #DV13 #AndroidPerf Non-Rectangular Clipping Detection

  93. #DV13 #AndroidPerf

  94. #DV13 #AndroidPerf Overdraw debug

  95. #DV13 #AndroidPerf

  96. #DV13 #AndroidPerf

  97. procstats: UI

  98. procstats: command line $ adb shell dumpsys procstats com.google.android.apps.maps COMMITTED

    STATS FROM 2013-11-05-18-04-58: * com.google.android.apps.maps / u0a60: TOTAL: 1.1% Service: 1.1% (Cached): 99% (98MB-98MB-99MB/96MB-97MB-97MB over 7) Run time Stats: Screen Off / Norm / +1h19m25s22ms Screen On / Norm / +10m43s963ms TOTAL: +1h30m8s985ms Start time: 2013-11-05 18:04:58 Total elapsed time: +5h9m53s44ms (complete) libdvm.so chromeview
  99. #DV13 #AndroidPerf GL Tracer

  100. #DV13 #AndroidPerf Systrace • Introduced in Jellybean 4.1 • Recent

    improvements - More framework tags - More categories - Easier to launch - App-level tags
  101. #DV13 #AndroidPerf Systrace • Introduced in Jellybean 4.1 • Recent

    improvements - More framework tags - More categories - Easier to launch - App-level tags Trace.beginSection("someLabel"); // stuff Trace.endSection();
  102. #DV13 #AndroidPerf Android Studio System Information

  103. #DV13 #AndroidPerf

  104. #DV13 #AndroidPerf

  105. Performance Tips

  106. #DV13 #AndroidPerf Bitmap Reuse mBitmapCache = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888); mBitmapOptions.inBitmap

    = mBitmapCache; mBitmapOptions.inSampleSize = 1; Bitmap newBitmap; if (mCheckBox.isChecked()) { newBitmap = BitmapFactory.decodeResource( getResources(), images[index], mBitmapOptions); } else { newBitmap = BitmapFactory.decodeResource( getResources(), images[index]); } mImageView.setImageBitmap(newBitmap);
  107. #DV13 #AndroidPerf Atlas • Popular in games, on web sites,

    etc… - Also called “sprite sheets“ • Can increase performance - Reduce number of OpenGL driver calls - Reduce number of GPU state changes - Better merging of draw calls
  108. #DV13 #AndroidPerf Atlas example 10 photos Drawn column by column

  109. #DV13 #AndroidPerf Atlas source

  110. #DV13 #AndroidPerf Loading the atlas 1/4 • res/raw/atlas.txt • Format:

    atlas_name ImageName,left,top,right,bottom ImageName,left,top,right,bottom ImageName,left,top,right,bottom
  111. #DV13 #AndroidPerf Loading the atlas 2/4 atlas Mountain,1,1,301,201 Gecko,302,1,602,201 Seahorse,603,1,903,201

    Camera,904,1,1204,201 Fish,1205,1,1505,201 Plasma,1,202,301,402 Grass,302,202,602,402 Photographer,603,202,903,402 Lights,904,202,1204,402 Flower,1205,202,1505,402
  112. #DV13 #AndroidPerf Loading the atlas 3/4 String line = reader.readLine();

    Resources res = getContext().getResources(); int atlasId = res.getIdentifier(line, "drawable", getContext().getPackageName()); mAtlas = BitmapFactory.decodeResource(res, atlasId);
  113. #DV13 #AndroidPerf Loading the atlas 3/4 String line = reader.readLine();

    Resources res = getContext().getResources(); int atlasId = res.getIdentifier(line, "drawable", getContext().getPackageName()); mAtlas = BitmapFactory.decodeResource(res, atlasId);
  114. #DV13 #AndroidPerf Loading the atlas 3/4 String line = reader.readLine();

    Resources res = getContext().getResources(); int atlasId = res.getIdentifier(line, "drawable", getContext().getPackageName()); mAtlas = BitmapFactory.decodeResource(res, atlasId);
  115. #DV13 #AndroidPerf Loading the atlas 4/4 static class Entry {

    String name; final Rect src = new Rect(); } while ((line = reader.readLine()) != null) { String[] fields = line.split(","); Entry entry = new Entry(); entry.name = fields[0]; entry.src.set(parseInt(fields[1]), parseInt(fields[2]), parseInt(fields[3]), parseInt(fields[4])); mEntries.add(entry); }
  116. #DV13 #AndroidPerf Drawing the atlas protected void onDraw(Canvas canvas) {

    final int count = mEntries.size(); for (int i = 0; i < count; i++) { Entry entry = mEntries.get(i); int x = computeX(entry); int y = computeY(entry); mDst.set(x, y, x + entry.src.width(), y + entry.src.height()); canvas.drawBitmap(mAtlas, entry.src, mDst, null); } }
  117. #DV13 #AndroidPerf Drawing the atlas protected void onDraw(Canvas canvas) {

    final int count = mEntries.size(); for (int i = 0; i < count; i++) { Entry entry = mEntries.get(i); int x = computeX(entry); int y = computeY(entry); mDst.set(x, y, x + entry.src.width(), y + entry.src.height()); canvas.drawBitmap(mAtlas, entry.src, mDst, null); } }
  118. #DV13 #AndroidPerf Drawing the atlas protected void onDraw(Canvas canvas) {

    final int count = mEntries.size(); for (int i = 0; i < count; i++) { Entry entry = mEntries.get(i); int x = computeX(entry); int y = computeY(entry); mDst.set(x, y, x + entry.src.width(), y + entry.src.height()); canvas.drawBitmap(mAtlas, entry.src, mDst, null); } }
  119. #DV13 #AndroidPerf Atlas tips 1/2 • 1px transparent border around

    entries - Allows proper bilinear filtering - For scaling, rotation, perspective, etc. • Watch out for max texture size - Especially at xxhdpi - 2048x2048 is common - 4096x4096 on recent devices
  120. #DV13 #AndroidPerf

  121. #DV13 #AndroidPerf Atlas tips 2/2 • Disable blending for opaque

    entries • Use a Paint with the SRC blend mode - mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)) • Store this information in atlas file - Name,left,top,right,bottom,1 // 1=opaque, 0= transparent
  122. #DV13 #AndroidPerf Layout • Don’t use multi-pass layouts at the

    top of the tree - Very expensive • LinearLayout is multi-pass… sometimes - For children with a layout_weight • RelativeLayout is always multi-pass
  123. #DV13 #AndroidPerf Tips for LinearLayout • Vertical layouts - Set

    height to 0dp for children with a weight • Horizontal layouts - Set width to 0dp for children with a weight - And set baselineAligned=”false” on LinearLayout • These tips don’t always apply
  124. #DV13 #AndroidPerf Tips for RelativeLayout • Don’t use it

  125. #DV13 #AndroidPerf Tips for RelativeLayout • Alright you can use

    it • But be careful
  126. Non-Rectangular Clipping 59 @Override protected void onDraw(Canvas canvas) { //

    Keep the jellybeans canvas.clipRect(l, t, r, b); // Rotate the jar canvas.rotate(-30.0f, pX, pY); // Draw the jar canvas.drawBitmap(mJellyBeans, x, y, null); }
  127. 60

  128. 1. Clip 60

  129. 2. Rotate 60

  130. 3. Draw 60

  131. 60

  132. 61 @Override protected void onDraw(Canvas canvas) { // Rotate the

    jar canvas.rotate(-30.0f, pX, pY); // Keep the jellybeans canvas.clipRect(l, t, r, b); // Draw the jar canvas.drawBitmap(mJellyBeans, x, y, null); }
  133. 62

  134. 1. Rotate 62

  135. 2. Clip 62

  136. 3. Draw 62

  137. 62

  138. Stencil buffer 63

  139. Stencil buffer 63

  140. #DV13 #AndroidPerf Don’t Update Layers • Avoid invalidating layered views/containers

    - Don’t change view or child views, remove children, add children, ... view.setLayerType(View.LATER_TYPE_HARDWARE, null); // run animation view.setLayerType(View.LAYER_TYPE_NONE, null); // or view.animate().alpha(0).withLayer();
  141. Using the Tools

  142. #DV13 #AndroidPerf Systrace • Overall system performance

  143. #DV13 #AndroidPerf For More Information • Google I/O talks •

    Parleys.com talks • Devbytes on YouTube Chet graphics-geek.blogspot.com google.com/+ChetHaase @chethaase Romain: curious-creature.org google.com/+RomainGuy @romainguy