debugging arts of the ninja masters

96
Monday, June 1, 2009

Upload: best-tech-videos

Post on 15-Nov-2014

144 views

Category:

Documents


0 download

DESCRIPTION

Ever have one of those days where your application just doesn't run correctly, and you can't figure out why? Well, we've been there, and we're going to show you how to fix it. In this session, Justin Mattson will school you on the advanced usage of Android debugging tools like traceview, the hierarchy viewer, and the instrumentation system. He'll also present several case studies where Google used these tools to solve real world problems, and show you the before-and-after results.Watch a video at http://www.bestechvideos.com/2009/06/04/google-i-o-2009-debugging-arts-of-the-ninja-masters

TRANSCRIPT

Page 1: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 2: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 3: Debugging Arts of the Ninja Masters

Debugging Arts of the Ninja MastersJustin MattsonDeveloper AdvocateAndroid Team @ Google28/5/2009

Monday, June 1, 2009

Page 4: Debugging Arts of the Ninja Masters

3

Agenda

• Tool tour– logcat– traceview– hierarchyviewer

• Real world usage• Pop quiz!• Q&A (pop quiz for me)

Monday, June 1, 2009

Page 5: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 6: Debugging Arts of the Ninja Masters

logcat

Monday, June 1, 2009

Page 7: Debugging Arts of the Ninja Masters

5

The dialog of death

Monday, June 1, 2009

Page 8: Debugging Arts of the Ninja Masters

6

ForensicsWhere to begin the autopsy

Monday, June 1, 2009

Page 9: Debugging Arts of the Ninja Masters

7

logcatYour news feed

Monday, June 1, 2009

Page 10: Debugging Arts of the Ninja Masters

8

logcat Levels Defined

• [E]rror– A unexpected critical or non-recoverable failure happened

• [W]arning– Something bad happened, but it was handled gracefully

• [I]nfo– An important event occurred

• [D]ebug– Something happened that may be useful in isolating a problem

• [V]erbose– Something occurred in the normal course of operation that was

expected.

Monday, June 1, 2009

Page 11: Debugging Arts of the Ninja Masters

9

A simple caseThe code can't break!

public class UriReader extends Thread { public String uriToRead = null; @Override public void run() { DefaultHttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(uriToRead); try { InputStream reader = client.execute(request).getEntity().getContent(); while (reader.read() != -1); } catch (ClientProtocolException e) { Log.w(TAG, "Protocol exception while reading URL."); } catch (IOException e) { Log.e(TAG, "General I/O exception, exact type is: " + e.getClass().getCanonicalName()); } } }

Monday, June 1, 2009

Page 12: Debugging Arts of the Ninja Masters

10

The scene of the crime

Monday, June 1, 2009

Page 13: Debugging Arts of the Ninja Masters

11

Take a good look around

Monday, June 1, 2009

Page 14: Debugging Arts of the Ninja Masters

12

The dialog of despair

Monday, June 1, 2009

Page 15: Debugging Arts of the Ninja Masters

13

Warning signsWhat’s that noise?

• Same process id, similar object count, similar sizes

Monday, June 1, 2009

Page 16: Debugging Arts of the Ninja Masters

14

Data Management

• Filters– TAG:SEVERITY

• Smart tagging– Meaningful– Related

• !SPAM– Precise– Concise– Privacy sensitive

Monday, June 1, 2009

Page 17: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 18: Debugging Arts of the Ninja Masters

traceview

Monday, June 1, 2009

Page 19: Debugging Arts of the Ninja Masters

16

tracing and traceview

• Records every function entry and exit point• Records how long execution took• Provides a graphical representation of collected data

– Timeline view– Call tree view

• Is a must-use for any developer serious about performance

Monday, June 1, 2009

Page 20: Debugging Arts of the Ninja Masters

17

How to start tracing

public class ProfiledActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { Debug.startMethodTracing(); } ... public void onPause() { Debug.stopMethodTracing(); }}

• Starting and stopping trace data collection is simple

• Controls tracing for entire VM• Tracing only what you need simplifies analysis

• Tracing has a big impact on performance

justin$ adb shell am profile com.example.foo profile start /sdcard/trace_file...justin$ adb shell am profile com.example.foo stop

Monday, June 1, 2009

Page 21: Debugging Arts of the Ninja Masters

18

Execution timeline

Monday, June 1, 2009

Page 22: Debugging Arts of the Ninja Masters

19

Function statistics

Monday, June 1, 2009

Page 23: Debugging Arts of the Ninja Masters

20

Function statisticsDetails

• Name• “Incl %” - percentage of time including descendants• Inclusive - raw execution time including descendants• “Excl %” - percentage of time sans descendants• Exclusive - time spent executing code only within this function• “Calls+Recur Calls/Total” - Number of times this method is called• Time/Call - Average execution time per call

Monday, June 1, 2009

Page 24: Debugging Arts of the Ninja Masters

21

Getting to the bottom (or top) of things

• The source of the issue may be above or below your code• traceview allows you to easily navigate the call tree

Monday, June 1, 2009

Page 25: Debugging Arts of the Ninja Masters

21

Getting to the bottom (or top) of things

• The source of the issue may be above or below your code• traceview allows you to easily navigate the call tree

Monday, June 1, 2009

Page 26: Debugging Arts of the Ninja Masters

22

Optimize reality

• traceview gives you a lot of power, take advantage of it• Design sensibly, build proof of concept, test, and optimize

Monday, June 1, 2009

Page 27: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 28: Debugging Arts of the Ninja Masters

HierarchyViewer

Monday, June 1, 2009

Page 29: Debugging Arts of the Ninja Masters

24

Exploring the UI with HierarchyViewer

Monday, June 1, 2009

Page 30: Debugging Arts of the Ninja Masters

25

Climbing the tree

Monday, June 1, 2009

Page 31: Debugging Arts of the Ninja Masters

25

Climbing the tree

Monday, June 1, 2009

Page 32: Debugging Arts of the Ninja Masters

26

Questionable families

• “Infertile parents” - layout with no or single layout children

• “Clones” - parents with same-type children

Monday, June 1, 2009

Page 33: Debugging Arts of the Ninja Masters

27

<merge /> your @includes

<merge xmlns:android=”http://schemas.android.com/apk/res/android”> <TextView android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:text=”@string/header_section” android:textColor=”@colors/header_color” /> <ImageView android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:src=”@drawable/logo” /></merge>

• Merge is a placeholder layout• Children of <merge> go into the layout where they are included

Monday, June 1, 2009

Page 34: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 35: Debugging Arts of the Ninja Masters

Traveler’s Tales: Betrayal

Monday, June 1, 2009

Page 36: Debugging Arts of the Ninja Masters

29

TraceView on a shipping product

• Why is something running on the main thread for that long?• Must be a network request someone forgot to move to a thread

Monday, June 1, 2009

Page 37: Debugging Arts of the Ninja Masters

30

com.ibm.icu4jni.util.Resources.getTimeZonesNative

• A call about time zones is taking this long?• Wait, I’m not even doing anything with time zones

Monday, June 1, 2009

Page 38: Debugging Arts of the Ninja Masters

30

com.ibm.icu4jni.util.Resources.getTimeZonesNative

• A call about time zones is taking this long?• Wait, I’m not even doing anything with time zones

Monday, June 1, 2009

Page 39: Debugging Arts of the Ninja Masters

30

com.ibm.icu4jni.util.Resources.getTimeZonesNative

• A call about time zones is taking this long?• Wait, I’m not even doing anything with time zones

Monday, June 1, 2009

Page 40: Debugging Arts of the Ninja Masters

31

Fixing the problem

• Move the call• De-prioritize its execution• Result: Better perceived startup time

Monday, June 1, 2009

Page 41: Debugging Arts of the Ninja Masters

31

Fixing the problem

• Move the call• De-prioritize its execution• Result: Better perceived startup time

Monday, June 1, 2009

Page 42: Debugging Arts of the Ninja Masters

32

Key Learnings

• Trust no one

• A little profiling goes a long way

• Priority matters

Monday, June 1, 2009

Page 43: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 44: Debugging Arts of the Ninja Masters

Traveler’s Tales: Finding shortcuts

Monday, June 1, 2009

Page 45: Debugging Arts of the Ninja Masters

34

Search for hidden inefficiencies

• Look at the function listing for less obvious performance issues

• Sort by exclusive execution– Shows inside which methods the program spends most of its time– Long average time methods with a few calls are good targets– Explore reducing and eliminating these calls

Monday, June 1, 2009

Page 46: Debugging Arts of the Ninja Masters

35

Search for hidden inefficiencies

Monday, June 1, 2009

Page 47: Debugging Arts of the Ninja Masters

36

Take a look around

• Explore ancestors and descendants of the method• Use timeline line view to check what happens before and after

the method

Monday, June 1, 2009

Page 48: Debugging Arts of the Ninja Masters

37

Take a look around

Monday, June 1, 2009

Page 49: Debugging Arts of the Ninja Masters

37

Take a look around

Monday, June 1, 2009

Page 50: Debugging Arts of the Ninja Masters

38

Iterate the route into a circle (square?)

Monday, June 1, 2009

Page 51: Debugging Arts of the Ninja Masters

38

Iterate the route into a circle (square?)

Parse response

Monday, June 1, 2009

Page 52: Debugging Arts of the Ninja Masters

38

Iterate the route into a circle (square?)

Parse response Create B

itmap

Monday, June 1, 2009

Page 53: Debugging Arts of the Ninja Masters

38

Iterate the route into a circle (square?)

Parse response Create B

itmap

Compress Bitmap

Monday, June 1, 2009

Page 54: Debugging Arts of the Ninja Masters

38

Iterate the route into a circle (square?)

Parse response Create B

itmap

Compress BitmapAdd

resu

lt to

cac

he

Monday, June 1, 2009

Page 55: Debugging Arts of the Ninja Masters

39

Fixing the problem

• Read in the full response• Store the PNG• Inflate Bitmap from PNG data• Discard PNG data

• Result: Decrease startup time by 350ms – 2% in “debug time”, larger real time effect since its native code

Monday, June 1, 2009

Page 56: Debugging Arts of the Ninja Masters

40

Key Learnings

• Big is beautiful

• Explore the area first

• Three rights can make a left

Monday, June 1, 2009

Page 57: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 58: Debugging Arts of the Ninja Masters

Traveler’s Tales: Packing mistakes

Monday, June 1, 2009

Page 59: Debugging Arts of the Ninja Masters

42

Sorting by inclusive execution

• Includes execution time of methods code and its descendants• List is somewhat like a breadth-first traversal of the call tree

Monday, June 1, 2009

Page 60: Debugging Arts of the Ninja Masters

42

Sorting by inclusive execution

• Includes execution time of methods code and its descendants• List is somewhat like a breadth-first traversal of the call tree

Monday, June 1, 2009

Page 61: Debugging Arts of the Ninja Masters

43

Taking a look at the code

try { List<MyDataType> itemsProcessed = new ArrayList<MyDataType>(); for (int i = 0; i < source.getNumItems(); i++) { Item currentItem = source.get(i); MyDataType processedItem = new MyDataType(currentItem); itemsProcessed.add(processedItem); itemProcessedCallback(itemsProcessed); }} catch (IOException e) { Log.W(TAG, “Reading data failed, retrying”);} catch (JSONException e) { Log.E(TAG, “JSON parsing failed”);}

• Items will be processed several times, this seems wrong

Monday, June 1, 2009

Page 62: Debugging Arts of the Ninja Masters

44

Fixing the problem

• Bug introduced when exception handling was refactored

• Result: Fewer calls to callback, 5% decrease in startup time

try { List<MyDataType> itemsProcessed = new ArrayList<MyDataType>(); for (int i = 0; i < source.getNumItems(); i++) { Item currentItem = source.get(i); MyDataType processedItem = new MyDataType(currentItem); itemsProcessed.add(processedItem); } itemProcessedCallback(itemsProcessed);} catch (IOException e) { Log.W(TAG, “Reading data failed, retrying”);} catch (JSONException e) { Log.E(TAG, “JSON parsing failed”);}

Monday, June 1, 2009

Page 63: Debugging Arts of the Ninja Masters

45

Key Learnings

• Each angle of approach is valuable

• Analyzing performance can reveal unknown bugs

Monday, June 1, 2009

Page 64: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 65: Debugging Arts of the Ninja Masters

Traveler’s Tales: Consolidating containers

Monday, June 1, 2009

Page 66: Debugging Arts of the Ninja Masters

47

A “simple” layout examined

Monday, June 1, 2009

Page 67: Debugging Arts of the Ninja Masters

47

A “simple” layout examined

Monday, June 1, 2009

Page 68: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 69: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 70: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 71: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 72: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 73: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 74: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 75: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 76: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 77: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 78: Debugging Arts of the Ninja Masters

48

Fixing the Problem

Monday, June 1, 2009

Page 79: Debugging Arts of the Ninja Masters

49

Fixing the problem

Monday, June 1, 2009

Page 80: Debugging Arts of the Ninja Masters

49

Fixing the problem

Monday, June 1, 2009

Page 81: Debugging Arts of the Ninja Masters

50

If it looks the same, who cares?

• Flatten for aerodynamic performance

• RelativeLayouts adapt to their environment

• RelativeLayouts force you to think

Monday, June 1, 2009

Page 82: Debugging Arts of the Ninja Masters

51

Key Learnings

• Layouts are code too and will evolve iteratively

• LinearLayouts are simple to visualize and understand, but can result in overly complex, less flexible hierarchies

• Rationalization needs to happen to keep the layout comprehensible and efficient

INSERT GLUED TOGETHER UI GRAPHIC

Monday, June 1, 2009

Page 83: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 84: Debugging Arts of the Ninja Masters

Traveler’s Tales: Squeaky wheels

Monday, June 1, 2009

Page 85: Debugging Arts of the Ninja Masters

53

What’s that noise?

• Same process id, similar object count, similar sizes

Monday, June 1, 2009

Page 86: Debugging Arts of the Ninja Masters

54

Allocation Tracker

Monday, June 1, 2009

Page 87: Debugging Arts of the Ninja Masters

55

Allocation Tracking

Monday, June 1, 2009

Page 88: Debugging Arts of the Ninja Masters

56

Using the right tool

• Problem caused by old code– Used for speed and convenience, over-stayed its welcome

public static byte[] fetchUri(String url) { ... InputStream in = openUrl(url); byte[] response = new byte[0]; byte[] readChunk = new byte[384]; int byteSize = 0; while ( (byteSize = in.read(readChunk)) != -1) { byte[] alreadyRead = response; response = new byte[alreadyRead.length + byteSize]; mergeArrays(response, alreadyRead, readChunk); }}

Monday, June 1, 2009

Page 89: Debugging Arts of the Ninja Masters

57

Fixing the problem

• Rewrite code to fit the problem• Anticipate larger read sizes, read in pieces, zipper together only

at the end

• Result: 90% decrease in read times

public static byte[] fetchUri(String url) { ... InputStream in = openUrl(url); ArrayList <byte[]> responsePieces = new ArrayList <byte[]>(); byte[] readChunk = new byte[2048]; int biteSize = 0; int responseSize = 0; while ( (biteSize = in.read(readChunk)) != -1) { responsePieces.add(readChunk); responseSize += biteSize; readChunk = new byte[2048]; } byte[] fullResponse = new byte[responseSize]; mergeArrays(fullResponse, responseSize);}

Monday, June 1, 2009

Page 90: Debugging Arts of the Ninja Masters

58

Key Learnings

• Take care with reused or prototype code

• Log messages if code is used beyond tolerances

Monday, June 1, 2009

Page 91: Debugging Arts of the Ninja Masters

Monday, June 1, 2009

Page 92: Debugging Arts of the Ninja Masters

Pop quiz!

Monday, June 1, 2009

Page 93: Debugging Arts of the Ninja Masters

60

What’s gone wrong?

Monday, June 1, 2009

Page 94: Debugging Arts of the Ninja Masters

60

What’s gone wrong?

Monday, June 1, 2009

Page 95: Debugging Arts of the Ninja Masters

61

What change caused this slow down?

Monday, June 1, 2009

Page 96: Debugging Arts of the Ninja Masters

Q&A

Monday, June 1, 2009