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

Android Performance Analysis Tools

Android Performance Analysis Tools

An introduction to a couple of Android performance analysis tools, using a (simplified, anonymized) real-life example.

Snild Dolkow

October 08, 2014
Tweet

Other Decks in Programming

Transcript

  1. What we do Performance analysis and improvements System engineering All

    over the place: Kernel Libraries Android Framework Apps Talk
  2. Our example problem Left-to-right layout scrolls smoothly, right-to-left drops frames!

    A simplified example, but we had the same problem in one of our apps (everything in this talk is from Snild’s Moto G, though) Code available on GitHub
  3. Our example problem Left-to-right layout scrolls smoothly, right-to-left drops frames!

    A simplified example, but we had the same problem in one of our apps (everything in this talk is from Snild’s Moto G, though) Where do we start? Code available on GitHub
  4. On-device tools Available in Settings, Developer Options Force GPU rendering

    Show GPU view updates Show hardware layers updates
  5. On-device tools Available in Settings, Developer Options Force GPU rendering

    Show GPU view updates Show hardware layers updates Debug GPU overdraw
  6. On-device tools Available in Settings, Developer Options Force GPU rendering

    Show GPU view updates Show hardware layers updates Debug GPU overdraw etc...
  7. On-device tools Available in Settings, Developer Options Force GPU rendering

    Show GPU view updates Show hardware layers updates Debug GPU overdraw etc... But I like starting with Profile GPU rendering as bars
  8. Profile GPU rendering as bars For each frame, shows: building

    display lists (includes onDraw() in Java) time executing display lists time spent sending frame to surfaceflinger 16 ms deadline Note: does not include other stuff on main thread
  9. Profile GPU rendering as bars For each frame, shows: building

    display lists (includes onDraw() in Java) time executing display lists time spent sending frame to surfaceflinger 16 ms deadline Note: does not include other stuff on main thread
  10. Profile GPU rendering as bars For each frame, shows: building

    display lists (includes onDraw() in Java) time executing display lists time spent sending frame to surfaceflinger 16 ms deadline Note: does not include other stuff on main thread
  11. Profile GPU rendering as bars For each frame, shows: building

    display lists (includes onDraw() in Java) time executing display lists time spent sending frame to surfaceflinger 16 ms deadline Note: does not include other stuff on main thread So the display lists are slow? Let’s take a more detailed look...
  12. Systrace Best tool ever! System-wide Very low overhead Can show

    a lot: GC, resources, drawing, CPU freq...
  13. Systrace Best tool ever! System-wide Very low overhead Can show

    a lot: GC, resources, drawing, CPU freq... Custom blocks with Trace.beginSection() (since KitKat)
  14. Systrace Best tool ever! System-wide Very low overhead Can show

    a lot: GC, resources, drawing, CPU freq... Custom blocks with Trace.beginSection() (since KitKat) Available in Eclipse with ADT And as command-line tool (which is, of course, much more h4xx0rz) Later SDKs have made big improvements, so use a recent one
  15. Systrace My favorite tags sched thread names and state (RUNNING/RUNNABLE/SLEEPING)

    am Activity Manager: bindApplication, startActivity, pauseActivity... view measure, layout, draw res resource loads, including file path dalvik GC, thread suspension gfx buffer queues, VSYNC wm Window Manager input
  16. Systrace Results Confirmed: drawing display lists takes a long time.

    We can get a bit more context here, like surfaceflinger interaction.
  17. Debug GPU overdraw Red means bad Visualizes how many times

    each pixel is filled Transparent: 1x Blue: 2x Green: 3x Red: 4x Dark red: 5x or more Can give us a hint about the differences here
  18. Debug GPU overdraw Red means bad Visualizes how many times

    each pixel is filled Transparent: 1x Blue: 2x Green: 3x Red: 4x Dark red: 5x or more Can give us a hint about the differences here
  19. Debug GPU overdraw Red means bad Visualizes how many times

    each pixel is filled Transparent: 1x Blue: 2x Green: 3x Red: 4x Dark red: 5x or more Can give us a hint about the differences here Hm, what’s that red edge..?
  20. Tracer for OpenGL ES Saves every OpenGL call Can dump

    buffer each frame Can dump buffer on every glDraw* call Can dump textures on upload Easy to use in its own Eclipse perspective
  21. Tracer for OpenGL ES Lots of extra draw commands... and

    Save/ComposeLayer. Looks like we’re always drawing that fading edge.
  22. Tracer for OpenGL ES Lots of extra draw commands... and

    Save/ComposeLayer. Looks like we’re always drawing that fading edge. Pretty costly: Lots of extra GL state changes Breaks batching optimizations
  23. Tracer for OpenGL ES Lots of extra draw commands... and

    Save/ComposeLayer. Looks like we’re always drawing that fading edge. Pretty costly: Lots of extra GL state changes Breaks batching optimizations But... why?
  24. Tracer for OpenGL ES Lots of extra draw commands... and

    Save/ComposeLayer. Looks like we’re always drawing that fading edge. Pretty costly: Lots of extra GL state changes Breaks batching optimizations But... why? Time to start looking at the code. And maybe a little interactive debugging. Where does TextView call saveLayer()?
  25. The Bug saveLayer() is actually called in View.draw(), based on

    getLeftFadingEdgeStrength() This only happens in a very specific situation... android:singleLine=true android:ellipsize=none android:requiresFadingEdge=horizontal text is right aligned (e.g. RTL or gravity=right)
  26. The Bug saveLayer() is actually called in View.draw(), based on

    getLeftFadingEdgeStrength() This only happens in a very specific situation... android:singleLine=true android:ellipsize=none android:requiresFadingEdge=horizontal text is right aligned (e.g. RTL or gravity=right) getLeftFadingEdgeStrength() always returns 1.0 in this case ...even if the text actually fits
  27. The Bug saveLayer() is actually called in View.draw(), based on

    getLeftFadingEdgeStrength() This only happens in a very specific situation... android:singleLine=true android:ellipsize=none android:requiresFadingEdge=horizontal text is right aligned (e.g. RTL or gravity=right) getLeftFadingEdgeStrength() always returns 1.0 in this case ...even if the text actually fits The root problem seems to be in the text layout code ...which other people understand better than us.
  28. The Bug saveLayer() is actually called in View.draw(), based on

    getLeftFadingEdgeStrength() This only happens in a very specific situation... android:singleLine=true android:ellipsize=none android:requiresFadingEdge=horizontal text is right aligned (e.g. RTL or gravity=right) getLeftFadingEdgeStrength() always returns 1.0 in this case ...even if the text actually fits The root problem seems to be in the text layout code ...which other people understand better than us. A good thing about big companies: there’s (almost) always someone else to send the issue to. ;) Or you can try to get Google to fix it: https://code.google.com/p/android/issues/detail?id=77210
  29. Other tools we like TraceView Shows time in Java functions

    But disables JIT And has high overhead So don’t trust the numbers It’s still good for finding possible hotspots Hierarchy View Shows how your views are connected Inspect views’ contents Inspect views’ properties Profile measure, layout and draw times Remember: layout and measure times affect launch times! Doesn’t work by default on production devices ...but you can add Romain Guy’s ViewServer to your app.
  30. Thanks! Want to learn more? Watch everything with Romain Guy

    ;) Especially his Google IO talks Read Android Performance Case Study: Falcon Pro