Automated Historical Performance Analysis with kmemtracer

1,247 views

Published on

Material presented at the 12th Korea Android Conference, Oct. 2013.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,247
On SlideShare
0
From Embeds
0
Number of Embeds
61
Actions
Shares
0
Downloads
19
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Automated Historical Performance Analysis with kmemtracer

  1. 1. Automated Historical Performance Analysis with kmemtracer LG전자 이경민
  2. 2. Contents Why Automated Historical Performance Testing? kmemtracer: What and How? Enhancement I : Automating UI Interaction Enhancement II: Adding More Performance Metrics 12th Kandroid Conference - www.kandroid.org 2
  3. 3. If you can’t measure it, you can’t manage it. Peter F. Drucker (1909~2005) 12th Kandroid Conference - www.kandroid.org 3
  4. 4. If you can’t measure it, you can’t manage it. Peter F. Drucker (1909~2005) If you can’t automate the measurement of it, it is difficult to improve it. 12th Kandroid Conference - www.kandroid.org 4
  5. 5. Diversity or Fragmentation Platform Versions http://developer.android.com/about/dashboards/index.html 12th Kandroid Conference - www.kandroid.org 5
  6. 6. Diversity or Fragmentation Platform Versions Screen Sizes and Densities http://developer.android.com/about/dashboards/index.html 12th Kandroid Conference - www.kandroid.org 6
  7. 7. http://www.mactrast.com/2012/05/visualized-the-truth-about-android-fragmentation/ 12th Kandroid Conference - www.kandroid.org 7
  8. 8. Historical Performance Analysis Why Historical Analysis? Source: Memory and Performance at the 11th Korea Android Conference 12th Kandroid Conference - www.kandroid.org 8
  9. 9. Historical Performance Analysis Why Historical Analysis? Source: Memory and Performance at the 11th Korea Android Conference 12th Kandroid Conference - www.kandroid.org 9
  10. 10. Historical Performance Analysis Why Historical Analysis? Activity Navigation & Lifecycle Source: Memory and Performance at the 11th Korea Android Conference 12th Kandroid Conference - www.kandroid.org 10
  11. 11. How to Track Activity Navigation & Lifecycle? 12th Kandroid Conference - www.kandroid.org 11
  12. 12. How to Track Activity Navigation & Lifecycle? Override onCreate, onStart, … of your Activity classes 12th Kandroid Conference - www.kandroid.org 12
  13. 13. How to Track Activity Navigation & Lifecycle? Modify android.app.Activity in the framework 12th Kandroid Conference - www.kandroid.org 13
  14. 14. How to Track Activity Navigation & Lifecycle? Is there a way that does not require the modification of an application or framework? 12th Kandroid Conference - www.kandroid.org 14
  15. 15. How to Track Activity Navigation & Lifecycle? Is there a way that does not require the modification of an application or framework? Instrumentation 12th Kandroid Conference - www.kandroid.org 15
  16. 16. 12th Kandroid Conference - www.kandroid.org 16
  17. 17. Android instrumentation is a set of control methods or "hooks" in the Android system. These hooks control an Android component independently of its normal lifecycle. They also control how Android loads applications. (http://developer.android.com/tools/testing/testing_android.html) 12th Kandroid Conference - www.kandroid.org 17
  18. 18. Contents Why Automated Historical Performance Testing? kmemtracer: What and How? Enhancement I : Automating UI Interaction Enhancement II: Adding More Performance Metrics 12th Kandroid Conference - www.kandroid.org 18
  19. 19. Historical Analysis w/ kmemtracer Application Package Control android.test. Instrumentation TestRunner Test Package 12th Kandroid Conference - www.kandroid.org 19
  20. 20. Historical Analysis w/ kmemtracer https://github.com/snailee/kmemtracer-libs Application Package Control Track android.test. Instrumentation TestRunner org.kandroid. memtracer.Memory Instrumentation Test Package Trace Package 12th Kandroid Conference - www.kandroid.org 20
  21. 21. android.app.Instrumentation void void void void void void void void void void void void void callActivityOnCreate(Activity, Bundle) callActivityOnDestroy(Activity) callActivityOnNewIntent(Activity, Intent) callActivityOnPause(Activity) callActivityOnPostCreate(Activity, Bundle) callActivityOnRestart(Activity) callActivityOnRestoreInstanceState(Activity, Bundle) callActivityOnResume(Activity) callActivityOnSaveInstanceState(Activity, Bundle) callActivityOnStart(Activity) callActivityOnStop(Activity) callActivityOnUserLeaving(Activity) callApplicationOnCreate(Application) 12th Kandroid Conference - www.kandroid.org 21
  22. 22. android.app.Instrumentation void void void void void void void void void void void void void callActivityOnCreate(Activity, Bundle) callActivityOnDestroy(Activity) callActivityOnNewIntent(Activity, Intent) callActivityOnPause(Activity) callActivityOnPostCreate(Activity, Bundle) callActivityOnRestart(Activity) callActivityOnRestoreInstanceState(Activity, Bundle) callActivityOnResume(Activity) callActivityOnSaveInstanceState(Activity, Bundle) callActivityOnStart(Activity) callActivityOnStop(Activity) callActivityOnUserLeaving(Activity) callApplicationOnCreate(Application) Call for Control 12th Kandroid Conference - www.kandroid.org 22
  23. 23. android.app.Instrumentation void void void void void void void void void void void void void callActivityOnCreate(Activity, Bundle) callActivityOnDestroy(Activity) callActivityOnNewIntent(Activity, Intent) callActivityOnPause(Activity) callActivityOnPostCreate(Activity, Bundle) callActivityOnRestart(Activity) callActivityOnRestoreInstanceState(Activity, Bundle) callActivityOnResume(Activity) callActivityOnSaveInstanceState(Activity, Bundle) callActivityOnStart(Activity) callActivityOnStop(Activity) callActivityOnUserLeaving(Activity) callApplicationOnCreate(Application) Call for Control Override for Track 12th Kandroid Conference - www.kandroid.org 23
  24. 24. org.kandroid.memtracer.MemoryInstrumentation public class MemoryInstrumentation extends Instrumentation { private static final String ARGUMENT_INSTRUMENT_CLASS = "class"; private MemoryTracer mMemoryTracer; private String mMainActivityName; ... @Override public void onCreate(Bundle arguments) { mMainActivityName = arguments.getString(ARGUMENT_INSTRUMENT_CLASS); mMemoryTracer = createMemoryTracer(); mMemoryTracer.startTracing(getTargetContext().getPackageName()); start(); } @Override public void callActivityOnCreate(Activity activity, Bundle icicle) { String tag = activity.getLocalClassName()+"-OnCreate"; Bundle snapshot = mMemoryTracer.addSnapshot(tag); super.callActivityOnCreate(activity, icicle); } } 12th Kandroid Conference - www.kandroid.org 24
  25. 25. Tracing Performance Snapshots in kmemtracer public class MemoryInstrumentation extends Instrumentation { ... ... } 12th Kandroid Conference - www.kandroid.org 25
  26. 26. Tracing Performance Snapshots in kmemtracer public class MemoryInstrumentation extends Instrumentation { ... private MemoryTracer mMemoryTracer; ... @Override public void onCreate(Bundle arguments) { ... mMemoryTracer = createMemoryTracer(); ... } ... Create an instance of MemoryTracer ... } 12th Kandroid Conference - www.kandroid.org 26
  27. 27. Tracing Performance Snapshots in kmemtracer public class MemoryInstrumentation extends Instrumentation { ... private MemoryTracer mMemoryTracer; ... @Override public void onCreate(Bundle arguments) { ... mMemoryTracer = createMemoryTracer(); ... } ... @Override public void callActivityOnCreate(Activity activity, Bundle icicle) { String tag = activity.getLocalClassName()+"-OnCreate"; Bundle snapshot = mMemoryTracer.addSnapshot(tag); ... } ... } Create an instance of MemoryTracer Add performance snapshot 12th Kandroid Conference - www.kandroid.org 27
  28. 28. MemoryTracer.addSnapshot public Bundle addSnapshot(String label) { ... 12th Kandroid Conference - www.kandroid.org 28
  29. 29. MemoryTracer.addSnapshot public Bundle addSnapshot(String label) { ... long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); ... Get usage data 12th Kandroid Conference - www.kandroid.org 29
  30. 30. MemoryTracer.addSnapshot public Bundle addSnapshot(String label) { ... long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); ... Bundle snapshot = new Bundle(); snapshot.putString(METRIC_KEY_LABEL, label); ... snapshot.putLong(METRIC_KEY_NATIVE_SIZE, nativeMax); snapshot.putLong(METRIC_KEY_NATIVE_ALLOCATED, nativeAllocated); snapshot.putLong(METRIC_KEY_NATIVE_FREE, nativeFree); ... Get usage data Save data to a bundle 12th Kandroid Conference - www.kandroid.org 30
  31. 31. MemoryTracer.addSnapshot public Bundle addSnapshot(String label) { ... long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); ... Bundle snapshot = new Bundle(); snapshot.putString(METRIC_KEY_LABEL, label); ... snapshot.putLong(METRIC_KEY_NATIVE_SIZE, nativeMax); snapshot.putLong(METRIC_KEY_NATIVE_ALLOCATED, nativeAllocated); snapshot.putLong(METRIC_KEY_NATIVE_FREE, nativeFree); ... if (mResultsWriter != null) { mResultsWriter.writeTraceSnapshot(snapshot); } return snapshot; } Get usage data Save data to a bundle Write date using ResultsWriter 12th Kandroid Conference - www.kandroid.org 31
  32. 32. MemoryTracerCsvWriter$writeTraceSnapshot public class MemoryTraceCsvWriter implements MemoryTracer.ResultsWriter { ... 12th Kandroid Conference - www.kandroid.org 32
  33. 33. MemoryTracerCsvWriter$writeTraceSnapshot public class MemoryTraceCsvWriter implements MemoryTracer.ResultsWriter { ... public MemoryTraceCsvWriter(String[] metricKeys) { mMetricKeys = metricKeys; } ... Create an instance with metrics to print 12th Kandroid Conference - www.kandroid.org 33
  34. 34. MemoryTracerCsvWriter$writeTraceSnapshot public class MemoryTraceCsvWriter implements MemoryTracer.ResultsWriter { ... public MemoryTraceCsvWriter(String[] metricKeys) { mMetricKeys = metricKeys; } ... private void openTraceFile(String filename) { ... mTraceOut = new PrintStream(new FileOutputStream(traceFile)); ... } ... Create an instance with metrics to print Open a trace file in the sdcard at init 12th Kandroid Conference - www.kandroid.org 34
  35. 35. MemoryTracerCsvWriter$writeTraceSnapshot public class MemoryTraceCsvWriter implements MemoryTracer.ResultsWriter { ... public MemoryTraceCsvWriter(String[] metricKeys) { mMetricKeys = metricKeys; } ... private void openTraceFile(String filename) { ... mTraceOut = new PrintStream(new FileOutputStream(traceFile)); ... } ... @Override public void writeTraceSnapshot(Bundle snapshot) { PrintStream out = mTraceOut; for (String key : mMetricKeys) { out.print(snapshot.get(key)); out.print(','); } out.println(); out.flush(); } ... } 12 Kandroid Conference - www.kandroid.org Create an instance with metrics to print Open a trace file in the sdcard at init Write snapshot to a line of the file th 35
  36. 36. How to Use kmemtracer? 12th Kandroid Conference - www.kandroid.org 36
  37. 37. How to Use kmemtracer? 1. Create an Android Test Project for the trace package. 12th Kandroid Conference - www.kandroid.org 37
  38. 38. How to Use kmemtracer? 1. Create an Android Test Project for the trace package. 2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory. 12th Kandroid Conference - www.kandroid.org 38
  39. 39. How to Use kmemtracer? 1. Create an Android Test Project for the trace package. 2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory. 3. Edit the <instrumentation> element in the Manifest file. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.apis.test" android:versionCode="1" android:versionName="1.0"> <instrumentation android:name="org.kandroid.memtracer.MemoryInstrumentation" android:targetPackage="com.example.android.apis" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:label="@string/app_name" android:icon="@drawable/ic_launcher“> <uses-library android:theme="android.text.runner“> </application> </manifest> 12th Kandroid Conference - www.kandroid.org 39
  40. 40. How to Use kmemtracer? 4. Install the trace package as well as the application package. $ adb install –r ApiDemos.apk $ adb install –r ApiDemosTest.apk 12th Kandroid Conference - www.kandroid.org 40
  41. 41. How to Use kmemtracer? 4. Install the trace package as well as the application package. $ adb install –r ApiDemos.apk $ adb install –r ApiDemosTest.apk 5. Start the instrumentation with ‘am instrument’ in the shell. $ > > > adb shell am instrument -e class com.example.android.apis.ApiDemos com.example.android.apis.tests/ org.kandroid.memtracer.MemoryInstrumentation 12th Kandroid Conference - www.kandroid.org 41
  42. 42. How to Use kmemtracer? 4. Install the trace package as well as the application package. $ adb install –r ApiDemos.apk $ adb install –r ApiDemosTest.apk 5. Start the instrumentation with ‘am instrument’ in the shell. $ > > > adb shell am instrument -e class com.example.android.apis.ApiDemos com.example.android.apis.tests/ org.kandroid.memtracer.MemoryInstrumentation 6. Do interact with the application. 12th Kandroid Conference - www.kandroid.org 42
  43. 43. How to Use kmemtracer? 4. Install the trace package as well as the application package. $ adb install –r ApiDemos.apk $ adb install –r ApiDemosTest.apk 5. Start the instrumentation with ‘am instrument’ in the shell. $ > > > adb shell am instrument -e class com.example.android.apis.ApiDemos com.example.android.apis.tests/ org.kandroid.memtracer.MemoryInstrumentation 6. Do interact with the application. 7. Pull the trace file ‘kmemtrace.csv’ from /sdcard/kmemtracer. $ adb pull /sdcard/kmemtracer/kmemtrace.csv . 12th Kandroid Conference - www.kandroid.org 43
  44. 44. How to Use kmemtracer? 8. Open the trace file with Excel and create charts. 12th Kandroid Conference - www.kandroid.org 44
  45. 45. Contents Why Automated Historical Performance Testing? kmemtracer: What and How? Enhancement I : Automating UI Interaction Enhancement II: Adding More Performance Metrics 12th Kandroid Conference - www.kandroid.org 45
  46. 46. Automate Controlling UI Application Package Control Track android.test. Instrumentation TestRunner org.kandroid. memtracer.Memory Instrumentation Test Package Trace Package 12th Kandroid Conference - www.kandroid.org 46
  47. 47. Automate Controlling UI Application Package Control Track android.test. Instrumentation TestRunner org.kandroid. memtracer.Memory Instrumentation Test Package Trace Package 12th Kandroid Conference - www.kandroid.org 47
  48. 48. Automate Controlling UI Application Package Control Track android.test. Instrumentation TestRunner org.kandroid. memtracer.Memory Instrumentation Test Package Trace Package 12th Kandroid Conference - www.kandroid.org 48
  49. 49. Three Alternatives 12th Kandroid Conference - www.kandroid.org 49
  50. 50. Three Alternatives Instrumentation API Level 1 ~ Single activity Framework APIs White-box http://developer.android.com/tools/testing/testing_android.html 12th Kandroid Conference - www.kandroid.org 50
  51. 51. Three Alternatives Instrumentation API Level 1 ~ Single activity Framework APIs White-box Robotium 2010/01 ~ Multiple activities High-level APIs White-box & black-box http://developer.android.com/tools/testing/testing_android.html https://code.google.com/p/robotium/ 12th Kandroid Conference - www.kandroid.org 51
  52. 52. Three Alternatives Instrumentation API Level 1 ~ Single activity Framework APIs White-box Robotium uiautomator 2010/01 ~ Multiple activities High-level APIs White-box & black-box API Level 17 ~ Multiple processes Simple APIs Black-box http://developer.android.com/tools/testing/testing_android.html https://code.google.com/p/robotium/ http://developer.android.com/tools/testing/testing_ui.html 12th Kandroid Conference - www.kandroid.org 52
  53. 53. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples 12th Kandroid Conference - www.kandroid.org 53
  54. 54. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples Click 12th Kandroid Conference - www.kandroid.org 54
  55. 55. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples Click 12th Kandroid Conference - www.kandroid.org 55
  56. 56. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples Click Scroll down 12th Kandroid Conference - www.kandroid.org 56
  57. 57. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples Click Scroll down 12th Kandroid Conference - www.kandroid.org 57
  58. 58. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples Click Scroll down Click 12th Kandroid Conference - www.kandroid.org 58
  59. 59. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples Click Scroll down Click 12th Kandroid Conference - www.kandroid.org 59
  60. 60. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples Click Scroll down Click Click 12th Kandroid Conference - www.kandroid.org 60
  61. 61. Case Study: ApiDemos https://github.com/snailee/deview-2013-samples Click Scroll down Click Click 12th Kandroid Conference - www.kandroid.org 61
  62. 62. Controlling UI Using Instrumentation 12th Kandroid Conference - www.kandroid.org 62
  63. 63. Controlling UI Using Instrumentation 1. Create an Android Test Project for the test package. $ android create test-project --main ../ApiDemos > –-name ApiDemosInstrumentTest --path ApiDemosInstrumentTest 12th Kandroid Conference - www.kandroid.org 63
  64. 64. Controlling UI Using Instrumentation 1. Create an Android Test Project for the test package. $ android create test-project --main ../ApiDemos > –-name ApiDemosInstrumentTest --path ApiDemosInstrumentTest 2. Add a test class inheriting ActivityInstrumentationTestCase2. public class ApiDemosInstrumentTest extends ActivityInstrumentationTestCase2<ApiDemos> { ... public ApiDemosInstrumentTest() { super(ApiDemos.class); } 12th Kandroid Conference - www.kandroid.org 64
  65. 65. Controlling UI Using Instrumentation 1. Create an Android Test Project for the test package. $ android create test-project --main ../ApiDemos > –-name ApiDemosInstrumentTest --path ApiDemosInstrumentTest 2. Add a test class inheriting ActivityInstrumentationTestCase2. public class ApiDemosInstrumentTest extends ActivityInstrumentationTestCase2<ApiDemos> { ... public ApiDemosInstrumentTest() { super(ApiDemos.class); } 3. Add a test method and launch the activity. public void testNavigate() { final ApiDemos apiDemos = getActivity(); ... } 12th Kandroid Conference - www.kandroid.org 65
  66. 66. Controlling UI Using Instrumentation 4. Find and act on a control. public void testNavigate() { ... 12th Kandroid Conference - www.kandroid.org 66
  67. 67. Controlling UI Using Instrumentation 4. Find and act on a control. public void testNavigate() ... final ListView demoList final View graphicsDemo assertNotNull("Graphics { Find a view to control = apiDemos.getListView(); = getChildViewByText(demoList, "Graphics"); demo should exist", graphicsDemo); 12th Kandroid Conference - www.kandroid.org 67
  68. 68. Controlling UI Using Instrumentation 4. Find and act on a control. public void testNavigate() ... final ListView demoList final View graphicsDemo assertNotNull("Graphics { Find a view to control = apiDemos.getListView(); = getChildViewByText(demoList, "Graphics"); demo should exist", graphicsDemo); apiDemos.runOnUiThread(new Runnable() { public void run() { int pos = demoList.getPositionForView(graphicsDemo); demoList.smoothScrollToPosition(pos); demoList.setSelection(pos); demoList.performItemClick(graphicsDemo, pos, graphicsDemo.getId()); } }); ... Act on the view 12th Kandroid Conference - www.kandroid.org 68
  69. 69. Controlling UI Using Instrumentation 4. Find and act on a control. public void testNavigate() ... final ListView demoList final View graphicsDemo assertNotNull("Graphics { Find a view to control = apiDemos.getListView(); = getChildViewByText(demoList, "Graphics"); demo should exist", graphicsDemo); apiDemos.runOnUiThread(new Runnable() { public void run() { int pos = demoList.getPositionForView(graphicsDemo); demoList.smoothScrollToPosition(pos); demoList.setSelection(pos); demoList.performItemClick(graphicsDemo, pos, graphicsDemo.getId()); } }); ... Act on the view 12th Kandroid Conference - www.kandroid.org 69
  70. 70. Controlling UI Using Instrumentation 4. Find and act on a control: getChildViewByText. private View getChildViewByText(ListView listView, String text) { 12th Kandroid Conference - www.kandroid.org 70
  71. 71. Controlling UI Using Instrumentation 4. Find and act on a control: getChildViewByText. private View getChildViewByText(ListView listView, String text) { View view = null; int count = listView.getCount(); Log.e(TAG, “no. children = " + count); for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); Iterate through child views 12th Kandroid Conference - www.kandroid.org 71
  72. 72. Controlling UI Using Instrumentation 4. Find and act on a control: getChildViewByText. private View getChildViewByText(ListView listView, String text) { View view = null; int count = listView.getCount(); Log.e(TAG, “no. children = " + count); for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); Log.e(TAG, i + "-th text view is " + textView); if (textView != null && textView.getText().equals(text)) { view = textView; break; } } return view; } Iterate through child views Compare texts 12th Kandroid Conference - www.kandroid.org 72
  73. 73. Controlling UI Using Instrumentation 4. Find and act on a control: getChildViewByText. private View getChildViewByText(ListView listView, String text) { View view = null; int count = listView.getCount(); Log.e(TAG, “no. children = " + count); for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); Log.e(TAG, i + "-th text view is " + textView); if (textView != null && textView.getText().equals(text)) { view = textView; break; } } return view; } com.example.android.apis.instrument.test.ApiDemosInstrumentTest: INSTRUMENTATION_RESULT: shortMsg=junit.framework.AssertionFailedError INSTRUMENTATION_RESULT: longMsg= junit.framework.AssertionFailedError: OpenGL ES demo should exist INSTRUMENTATION_CODE: 0 Iterate through child views Compare texts 12th Kandroid Conference - www.kandroid.org 73
  74. 74. Controlling UI Using Instrumentation 4. Find and act on a control: Revised getChildViewByText. private View getChildViewByText(final ListView listView, String text) { ... for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); if (textView != null && textView.getText().equals(text)) { view = textView; break; } if (textView == null) { final int lastPos = listView.getLastVisiblePosition(); getInstrumentation().runOnMainSync(new Runnable() { public void run() { listView.smoothScrollToPosition(lastPos + 5, lastPos); } }); getInstrumentation().waitForIdleSync(); i = listView.getFirstVisiblePosition(); } } return view; } 12th Kandroid Conference - www.kandroid.org 74
  75. 75. Controlling UI Using Instrumentation 4. Find and act on a control: Revised getChildViewByText. private View getChildViewByText(final ListView listView, String text) { ... for (int i = 0; i < count; i++) { TextView textView = (TextView) listView.getChildAt(i); if (textView != null && textView.getText().equals(text)) { view = textView; break; } if (textView == null) { final int lastPos = listView.getLastVisiblePosition(); getInstrumentation().runOnMainSync(new Runnable() { public void run() { listView.smoothScrollToPosition(lastPos + 5, lastPos); } }); getInstrumentation().waitForIdleSync(); i = listView.getFirstVisiblePosition(); } } return view; } Scroll down 12th Kandroid Conference - www.kandroid.org 75
  76. 76. Controlling UI Using Instrumentation 4. Find and act on a control: getPositionForChildViewByText. private int getPositionForChildViewByText(ListView listView, String text) { ListAdapter listAdapter = listView.getAdapter(); int count = listAdapter.getCount(); Log.e(TAG, "children: " + count); for (int i = 0; i < count; i++) { String itemText = (String) ((Map)listAdapter.getItem(i)).get("title"); Log.e(TAG, i + "-th text item " + itemText); if (itemText != null && itemText.equals(text)) { return i; } } return -1; } ... final ListView graphicsDemoList = graphicsDemoActivity.getListView(); int pos = getPositionForChildViewByText(graphicsDemoList, "OpenGL ES"); assertTrue("Cannot find OpenGL ES", pos != -1); ... 12th Kandroid Conference - www.kandroid.org 76
  77. 77. Controlling UI Using Instrumentation 4. Find and act on a control: getPositionForChildViewByText. private int getPositionForChildViewByText(ListView listView, String text) { ListAdapter listAdapter = listView.getAdapter(); int count = listAdapter.getCount(); Log.e(TAG, "children: " + count); for (int i = 0; i < count; i++) { String itemText = (String) ((Map)listAdapter.getItem(i)).get("title"); Log.e(TAG, i + "-th text item " + itemText); if (itemText != null && itemText.equals(text)) { return i; } } return -1; } ... final ListView graphicsDemoList = graphicsDemoActivity.getListView(); int pos = getPositionForChildViewByText(graphicsDemoList, "OpenGL ES"); assertTrue("Cannot find OpenGL ES", pos != -1); ... 12th Kandroid Conference - www.kandroid.org 77
  78. 78. Controlling UI Using Instrumentation 5. Monitor a new Activity to launch. public void testNavigate() { ... Instrumentation.ActivityMonitor graphicsDemoActivityMonitor = getInstrumentation().addMonitor( ApiDemos.class.getName(), null, false); final ApiDemos graphicsDemoActivity = (ApiDemos) graphicsDemoActivityMonitor.waitForActivity(); assertNotNull("Graphics Demo (ApiDemos) activity should not be null", graphicsDemoActivity); ... 12th Kandroid Conference - www.kandroid.org 78
  79. 79. Controlling UI Using Instrumentation 5. Monitor a new Activity to launch. public void testNavigate() { ... Instrumentation.ActivityMonitor graphicsDemoActivityMonitor = getInstrumentation().addMonitor( ApiDemos.class.getName(), null, false); final ApiDemos graphicsDemoActivity = (ApiDemos) graphicsDemoActivityMonitor.waitForActivity(); assertNotNull("Graphics Demo (ApiDemos) activity should not be null", graphicsDemoActivity); ... 6. Iterate step 4 & 5. 12th Kandroid Conference - www.kandroid.org 79
  80. 80. Controlling UI Using Instrumentation 7. Build and Install the test package. $ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk 12th Kandroid Conference - www.kandroid.org 80
  81. 81. Controlling UI Using Instrumentation 7. Build and Install the test package. $ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk 8. Run the test and see the result. $ adb shell am instrument -w > com.example.android.apis.instrument.test/ > android.test.InstrumentationTestRunner 12th Kandroid Conference - www.kandroid.org 81
  82. 82. Controlling UI Using Instrumentation 7. Build and Install the test package. $ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk 8. Run the test and see the result. $ adb shell am instrument -w > com.example.android.apis.instrument.test/ > android.test.InstrumentationTestRunner $ ant test 12th Kandroid Conference - www.kandroid.org 82
  83. 83. Controlling UI Using Robotium 12th Kandroid Conference - www.kandroid.org 83
  84. 84. Controlling UI Using Robotium 1. Create an Android Test Project for the test package. $ android create test-project --main ../ApiDemos > –-name ApiDemosRobotiumTest --path ApiDemosRobotiumTest 12th Kandroid Conference - www.kandroid.org 84
  85. 85. Controlling UI Using Robotium 1. Create an Android Test Project for the test package. $ android create test-project --main ../ApiDemos > –-name ApiDemosRobotiumTest --path ApiDemosRobotiumTest 2. Add ‘robotium-solo-<ver>.jar’ in the ‘libs’ directory. 12th Kandroid Conference - www.kandroid.org 85
  86. 86. Controlling UI Using Robotium 1. Create an Android Test Project for the test package. $ android create test-project --main ../ApiDemos > –-name ApiDemosRobotiumTest --path ApiDemosRobotiumTest 2. Add ‘robotium-solo-<ver>.jar’ in the ‘libs’ directory. 3. Add a test class inheriting ActivityInstrumentationTestCase2. public class ApiDemosRobotiumTest extends ActivityInstrumentationTestCase2<ApiDemos> { ... public ApiDemosRobotiumTest() { super(ApiDemos.class); } ... 12th Kandroid Conference - www.kandroid.org 86
  87. 87. Controlling UI Using Robotium 4. Create an instance of Solo in the setUp method and close open activities in the tearDown method. ... private Solo solo; ... @Override public void setUp() throws Exception { solo = new Solo(getInstrumentation(), getActivity()); } @Override public void tearDown() throws Exception { solo.finishOpenedActivities(); } ... 12th Kandroid Conference - www.kandroid.org 87
  88. 88. Controlling UI Using Robotium 4. Find and act on a control. public void testNavigate() { solo.assertCurrentActivity("Should be on ApiDemos", ApiDemos.class); solo.clickOnText("^Graphics$", 1, true); solo.assertCurrentActivity("Should be on a new ApiDemos", ApiDemos.class, true); solo.clickOnText("^OpenGL ES$", 1, true); solo.assertCurrentActivity("Should be on a new ApiDemos", ApiDemos.class, true); solo.clickOnText("^Kube$", 1, true); solo.assertCurrentActivity("Should be on a Kube", Kube.class, true); solo.sleep(3000); } 12th Kandroid Conference - www.kandroid.org 88
  89. 89. Controlling UI Using Robotium 6. Build and Install the test package. $ cd ApiDemosRobotiumTest $ ant debug $ adb install –r bin/ApiDemosRobotiumTest-debug.apk 12th Kandroid Conference - www.kandroid.org 89
  90. 90. Controlling UI Using Robotium 6. Build and Install the test package. $ cd ApiDemosRobotiumTest $ ant debug $ adb install –r bin/ApiDemosRobotiumTest-debug.apk 7. Run the test and see the result. $ adb shell am instrument -w > com.example.android.apis.robotium.test/ > android.test.InstrumentationTestRunner 12th Kandroid Conference - www.kandroid.org 90
  91. 91. Controlling UI Using Robotium 6. Build and Install the test package. $ cd ApiDemosRobotiumTest $ ant debug $ adb install –r bin/ApiDemosRobotiumTest-debug.apk 7. Run the test and see the result. $ adb shell am instrument -w > com.example.android.apis.robotium.test/ > android.test.InstrumentationTestRunner $ ant test 12th Kandroid Conference - www.kandroid.org 91
  92. 92. Controlling UI Using uiautomator 1. Create an Java Project for the test jar. 12th Kandroid Conference - www.kandroid.org 92
  93. 93. Controlling UI Using uiautomator 1. Create an Java Project for the test jar. 2. Add ‘android.jar’ and ‘uiautomator.jar’ in the build path. 12th Kandroid Conference - www.kandroid.org 93
  94. 94. Controlling UI Using uiautomator 1. Create an Java Project for the test jar. 2. Add ‘android.jar’ and ‘uiautomator.jar’ in the build path. 3. Add a test class inheriting UiAutomatorTestCase. public class ApiDemosUiAutoTest extends UiAutomatorTestCase { ... } 12th Kandroid Conference - www.kandroid.org 94
  95. 95. Controlling UI Using uiautomator 4. Launch ApiDemos. public void testNavigate() throws UiObjectNotFoundException { 12th Kandroid Conference - www.kandroid.org 95
  96. 96. Controlling UI Using uiautomator 4. Launch ApiDemos. public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); Press home button 12th Kandroid Conference - www.kandroid.org 96
  97. 97. Controlling UI Using uiautomator 4. Launch ApiDemos. public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); UiObject allAppsButton = new UiObject( new UiSelector().description("Apps")); allAppsButton.clickAndWaitForNewWindow(); 12th Kandroid Conference - www.kandroid.org Press home button Click ‘All Apps’ button 97
  98. 98. Controlling UI Using uiautomator 4. Launch ApiDemos. public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); UiObject allAppsButton = new UiObject( new UiSelector().description("Apps")); allAppsButton.clickAndWaitForNewWindow(); Press home button Click ‘All Apps’ button UiObject appsTab = new UiObject(new UiSelector().text("Apps")); appsTab.click(); Click ‘Apps’ tab 12th Kandroid Conference - www.kandroid.org 98
  99. 99. Controlling UI Using uiautomator 4. Launch ApiDemos. public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); UiObject allAppsButton = new UiObject( new UiSelector().description("Apps")); allAppsButton.clickAndWaitForNewWindow(); Press home button Click ‘All Apps’ button UiObject appsTab = new UiObject(new UiSelector().text("Apps")); appsTab.click(); Click ‘Apps’ tab UiScrollable appList = new UiScrollable( new UiSelector().scrollable(true)); appList.setAsHorizontalList(); UiObject apiDemos = appList.getChildByText( new UiSelector().className(TextView.class.getName()), "API Demos"); apiDemos.clickAndWaitForNewWindow(); Click ‘ApiDemos’ icon 12th Kandroid Conference - www.kandroid.org 99
  100. 100. Controlling UI Using uiautomator 4. Launch ApiDemos. public void testNavigate() throws UiObjectNotFoundException { getUiDevice().pressHome(); UiObject allAppsButton = new UiObject( new UiSelector().description("Apps")); allAppsButton.clickAndWaitForNewWindow(); Press home button Click ‘All Apps’ button UiObject appsTab = new UiObject(new UiSelector().text("Apps")); appsTab.click(); Click ‘Apps’ tab UiScrollable appList = new UiScrollable( new UiSelector().scrollable(true)); appList.setAsHorizontalList(); UiObject apiDemos = appList.getChildByText( new UiSelector().className(TextView.class.getName()), "API Demos"); apiDemos.clickAndWaitForNewWindow(); Click ‘ApiDemos’ icon Validate the launch of ‘ApiDemos’ UiObject apiDemosPackage = new UiObject( new UiSelector().packageName("com.example.android.apis")); assertTrue("Should be on ApiDemos", apiDemosPackage.exists()); ... 12th Kandroid Conference - www.kandroid.org 100
  101. 101. Controlling UI Using uiautomator 5. Find and act on a control. ... UiScrollable demoList = new UiScrollable( new UiSelector().className("android.widget.ListView")); UiObject graphicsDemo = demoList.getChildByText( new UiSelector().className(TextView.class.getName()), “Graphics"); graphicsDemo.clickAndWaitForNewWindow(); UiObject alphaBitmapDemo = new UiObject( new UiSelector().text(“AlphaBitmap")); assertTrue(“AlphaBitmap should be visible", alpahBitmapDemo.exists()); ... 12th Kandroid Conference - www.kandroid.org 101
  102. 102. Controlling UI Using uiautomator 5. Find and act on a control. ... UiScrollable demoList = new UiScrollable( new UiSelector().className("android.widget.ListView")); UiObject graphicsDemo = demoList.getChildByText( new UiSelector().className(TextView.class.getName()), “Graphics"); graphicsDemo.clickAndWaitForNewWindow(); UiObject alphaBitmapDemo = new UiObject( new UiSelector().text(“AlphaBitmap")); assertTrue(“AlphaBitmap should be visible", alpahBitmapDemo.exists()); ... 6. Iterate step 5. 12th Kandroid Conference - www.kandroid.org 102
  103. 103. Controlling UI Using uiautomator 7. Compile your test case into a JAR file. $ > $ $ android create uitest-project --name ApiDemosUiAutoTest --target 1 --path ApiDemosUiAutoTest cd ApiDemosUiAutoTest ant build 12th Kandroid Conference - www.kandroid.org 103
  104. 104. Controlling UI Using uiautomator 7. Compile your test case into a JAR file. $ > $ $ android create uitest-project --name ApiDemosUiAutoTest --target 1 --path ApiDemosUiAutoTest cd ApiDemosUiAutoTest ant build 8. Install the jar on your test device. $ adb push bin/ApiDemosUiAutoTest.jar /data/local/tmp/ 12th Kandroid Conference - www.kandroid.org 104
  105. 105. Controlling UI Using uiautomator 7. Compile your test case into a JAR file. $ > $ $ android create uitest-project --name ApiDemosUiAutoTest --target 1 --path ApiDemosUiAutoTest cd ApiDemosUiAutoTest ant build 8. Install the jar on your test device. $ adb push bin/ApiDemosUiAutoTest.jar /data/local/tmp/ 9. Run the test and view the test result. $ adb shell uiautomator runtest ApiDemosUiAutoTest.jar > –c com.example.android.apis.uiauto.test.ApiDemosUiAutoTest 12th Kandroid Conference - www.kandroid.org 105
  106. 106. Controlling UI Using uiautomator 7. Compile your test case into a JAR file. $ > $ $ android create uitest-project --name ApiDemosUiAutoTest --target 1 --path ApiDemosUiAutoTest cd ApiDemosUiAutoTest ant build 8. Install the jar on your test device. $ adb push bin/ApiDemosUiAutoTest.jar /data/local/tmp/ 9. Run the test and view the test result. $ adb shell uiautomator runtest ApiDemosUiAutoTest.jar > –c com.example.android.apis.uiauto.test.ApiDemosUiAutoTest $ ant test 12th Kandroid Conference - www.kandroid.org 106
  107. 107. Controlling UI Using uiautomator 7. Compile your test case into a JAR file. $ > $ $ android create uitest-project --name ApiDemosUiAutoTest --target 1 --path ApiDemosUiAutoTest cd ApiDemosUiAutoTest ant build 8. Install the jar on your test device. $ adb push bin/ApiDemosUiAutoTest.jar /data/local/tmp/ 9. Run the test and view the test result. $ adb shell uiautomator runtest ApiDemosUiAutoTest.jar > –c com.example.android.apis.uiauto.test.ApiDemosUiAutoTest $ ant test 12th Kandroid Conference - www.kandroid.org 107
  108. 108. Doing both Controlling and Tracking 12th Kandroid Conference - www.kandroid.org 108
  109. 109. Doing both Controlling and Tracking 1. Modify org.kandroid.memtracer.MemoryInstrumentation. public class MemoryInstrumentation extends InstrumentationTestRunner { ... @Override public void onCreate(Bundle arguments) { ... start(); super.onCreate(arguments); } @Override public void onStart() { String mainActivityName = getMainActivityName(); if (mainActivityName != null && mainActivityName.length() > 0) { launchMainActivity(getTargetContext().getPackageName(), getMainActivityName()); } else { super.onStart(); } } ... 12th Kandroid Conference - www.kandroid.org 109
  110. 110. Doing both Controlling and Tracking 1. Modify org.kandroid.memtracer.MemoryInstrumentation. public class MemoryInstrumentation extends InstrumentationTestRunner { ... @Override public void onCreate(Bundle arguments) { ... start(); super.onCreate(arguments); } @Override public void onStart() { String mainActivityName = getMainActivityName(); if (mainActivityName != null && mainActivityName.length() > 0) { launchMainActivity(getTargetContext().getPackageName(), getMainActivityName()); } else { super.onStart(); } } ... 12th Kandroid Conference - www.kandroid.org 110
  111. 111. Doing both Controlling and Tracking 1. Modify org.kandroid.memtracer.MemoryInstrumentation. public class MemoryInstrumentation extends InstrumentationTestRunner { ... @Override public void onCreate(Bundle arguments) { ... start(); super.onCreate(arguments); } @Override public void onStart() { String mainActivityName = getMainActivityName(); if (mainActivityName != null && mainActivityName.length() > 0) { launchMainActivity(getTargetContext().getPackageName(), getMainActivityName()); } else { super.onStart(); } } ... 12th Kandroid Conference - www.kandroid.org 111
  112. 112. Doing both Controlling and Tracking 1. Modify org.kandroid.memtracer.MemoryInstrumentation. public class MemoryInstrumentation extends InstrumentationTestRunner { ... @Override public void onCreate(Bundle arguments) { ... start(); super.onCreate(arguments); } @Override public void onStart() { String mainActivityName = getMainActivityName(); if (mainActivityName != null && mainActivityName.length() > 0) { launchMainActivity(getTargetContext().getPackageName(), getMainActivityName()); } else { super.onStart(); } } ... 12th Kandroid Conference - www.kandroid.org 112
  113. 113. Doing both Controlling and Tracking 2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory. 12th Kandroid Conference - www.kandroid.org 113
  114. 114. Doing both Controlling and Tracking 2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory. 3. Edit the <instrumentation> element in the manifest file. 12th Kandroid Conference - www.kandroid.org 114
  115. 115. Doing both Controlling and Tracking 2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory. 3. Edit the <instrumentation> element in the manifest file. 4. Build and Install the test package. $ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk 12th Kandroid Conference - www.kandroid.org 115
  116. 116. Doing both Controlling and Tracking 2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory. 3. Edit the <instrumentation> element in the manifest file. 4. Build and Install the test package. $ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk 5. Run the test and see the result. $ adb shell am instrument -w > com.example.android.apis.instrument.test/ > org.kandroid.memtracer.MemoryInstrumentation 12th Kandroid Conference - www.kandroid.org 116
  117. 117. Doing both Controlling and Tracking 2. Add ‘kmemtracer-libs.jar’ in the ‘libs’ directory. 3. Edit the <instrumentation> element in the manifest file. 4. Build and Install the test package. $ cd ApiDemosInstrumentTest $ ant debug $ adb install –r bin/ApiDemosInstrumentTest-debug.apk 5. Run the test and see the result. $ adb shell am instrument -w > com.example.android.apis.instrument.test/ > org.kandroid.memtracer.MemoryInstrumentation 6. Pull the trace file ‘kmemtrace.csv’ from /sdcard/kmemtracer. $ adb pull /sdcard/kmemtracer/kmemtrace.csv . 12th Kandroid Conference - www.kandroid.org 117
  118. 118. Comparison Instrument Robotium uiautomator Compatibility O O X Multi-activities  O O Multi-processes X X O Ease of APIs X O  Black box X  O 12th Kandroid Conference - www.kandroid.org 118
  119. 119. Contents Why Automated Historical Performance Testing? kmemtracer: What and How? Enhancement I : Automating UI Interaction Enhancement II: Adding More Performance Metrics 12th Kandroid Conference - www.kandroid.org 119
  120. 120. What to Measure? Rendering (or GUI) Performance Frame Rate (FPS), Frame Time , Jankiness, Input Latency, … Resource Consumption Memory, CPU, I/O (Disk, Network), Battery, … Network Performance Response time, Throughput, … … 12th Kandroid Conference - www.kandroid.org 120
  121. 121. What to Measure? Rendering (or GUI) Performance Frame Rate (FPS), Frame Time , Jankiness, Input Latency, … Resource Consumption Memory, CPU, I/O (Disk, Network), Battery, … Network Performance Response time, Throughput, … … 12th Kandroid Conference - www.kandroid.org 121
  122. 122. How to Measure Resource Consumption? 12th Kandroid Conference - www.kandroid.org 122
  123. 123. How to Measure Resource Consumption? cmds API 12th Kandroid Conference - www.kandroid.org 123
  124. 124. How to Measure Resource Consumption? cmds API Public Internal 12th Kandroid Conference - www.kandroid.org 124
  125. 125. How to Measure Resource Consumption? cmds API Public Internal Android 12th Kandroid Conference - www.kandroid.org Linux 125
  126. 126. How to Measure Resource Consumption? cmds API Public Internal Android Easy Linux Flexible 12th Kandroid Conference - www.kandroid.org 126
  127. 127. Measuring Memory Usage 12th Kandroid Conference - www.kandroid.org 127
  128. 128. Measuring Memory Usage Public android.app.ActivityManager.MemoryInfo android.os.Debug android.os.Debug.MemoryInfo 12th Kandroid Conference - www.kandroid.org 128
  129. 129. Measuring Memory Usage Public Internal android.app.ActivityManager.MemoryInfo android.os.Debug android.os.Debug.MemoryInfo dalvik.system.VMDebug 12th Kandroid Conference - www.kandroid.org 129
  130. 130. Measuring Memory Usage Public Internal Android android.app.ActivityManager.MemoryInfo android.os.Debug android.os.Debug.MemoryInfo dalvik.system.VMDebug adb shell dumpsys meminfo [pid|pname] adb shell dumpsys gfxinfo [pid|pname] adb shell procrank 12th Kandroid Conference - www.kandroid.org 130
  131. 131. Measuring Memory Usage Public Internal Android Linux android.app.ActivityManager.MemoryInfo android.os.Debug android.os.Debug.MemoryInfo dalvik.system.VMDebug adb shell dumpsys meminfo [pid|pname] adb shell dumpsys gfxinfo [pid|pname] adb shell procrank adb shell cat /proc/meminfo adb shell cat /proc/<pid>/[s]maps adb shell cat /proc/vmstat adb shell top adb shell ps 12th Kandroid Conference - www.kandroid.org 131
  132. 132. Measuring Memory Usage: dumpsys meminfo $ adb shell dumpsys meminfo com.example.android.apis Applications Memory Usage (kB): Uptime: 93065 Realtime: 93065 ** MEMINFO in pid 1259 [com.example.android.apis] ** native dalvik other total size: 3548 5831 N/A 9379 allocated: 3475 3335 N/A 6810 free: 48 2496 N/A 2544 (Pss): 699 382 4889 5970 (shared dirty): 1500 1876 8356 11732 (priv dirty): 628 40 2472 3140 ... GB (API Level 10) 12th Kandroid Conference - www.kandroid.org 132
  133. 133. Measuring Memory Usage: dumpsys meminfo $ adb shell dumpsys meminfo com.example.android.apis Applications Memory Usage (kB): Uptime: 93065 Realtime: 93065 ** MEMINFO in pid 1259 [com.example.android.apis] ** native dalvik other total size: 3548 5831 N/A 9379 allocated: 3475 3335 N/A 6810 free: 48 2496 N/A 2544 (Pss): 699 382 4889 5970 (shared dirty): 1500 1876 8356 11732 (priv dirty): 628 40 2472 3140 ... GB (API Level 10) 12th Kandroid Conference - www.kandroid.org 133
  134. 134. Measuring Memory Usage: dumpsys meminfo $ adb shell dumpsys meminfo com.example.android.apis ... ** MEMINFO in pid 1875 [com.example.android.apis] ** Shared Private Heap Heap Pss Dirty Dirty Size Alloc -------------------------Native 1377 1256 1300 12084 7332 Dalvik 5274 5476 4952 6260 5712 Stack 76 12 76 Cursor 0 0 0 Ashmem 0 0 0 Other dev 4 20 0 .so mmap 1526 4836 592 .jar mmap 0 0 0 .apk mmap 267 0 0 .ttf mmap 5 0 0 .dex mmap 1085 0 0 Other mmap 18 8 4 Unknown 824 0 824 TOTAL 10456 11608 7748 18344 13044 ... Heap Free -----567 548 1115 JB (API Level 18) 12th Kandroid Conference - www.kandroid.org 134
  135. 135. Measuring Memory Usage: dumpsys meminfo $ adb shell dumpsys meminfo com.example.android.apis ... ** MEMINFO in pid 1875 [com.example.android.apis] ** Shared Private Heap Heap Pss Dirty Dirty Size Alloc -------------------------Native 1377 1256 1300 12084 7332 Dalvik 5274 5476 4952 6260 5712 Stack 76 12 76 Cursor 0 0 0 Ashmem 0 0 0 Other dev 4 20 0 .so mmap 1526 4836 592 .jar mmap 0 0 0 .apk mmap 267 0 0 .ttf mmap 5 0 0 .dex mmap 1085 0 0 Other mmap 18 8 4 Unknown 824 0 824 TOTAL 10456 11608 7748 18344 13044 ... Heap Free -----567 548 1115 JB (API Level 18) 12th Kandroid Conference - www.kandroid.org 135
  136. 136. https://android.googlesource.com/platform/frameworks/base.git/+/0e3328fbdd3845b0e2bec364e951498eaee6b079 12th Kandroid Conference - www.kandroid.org 136
  137. 137. How ‘dumpsys meminfo’ works? adb shell dumpsys meminfo [-a] [-oom] [-process] 12th Kandroid Conference - www.kandroid.org 137
  138. 138. How ‘dumpsys meminfo’ works? adb shell dumpsys meminfo [-a] [-oom] [-process] com.android.server.am. ActivityManagerService 12th Kandroid Conference - www.kandroid.org 138
  139. 139. How ‘dumpsys meminfo’ works? adb shell dumpsys meminfo [-a] [-oom] [-process] com.android.server.am. ActivityManagerService android.app.ActivityThread. android.app.ActivityThread. android.app.ActivityThread. ApplicationThread ApplicationThread ApplicationThread android.os Debug 12th Kandroid Conference - www.kandroid.org 139
  140. 140. How ‘dumpsys meminfo’ works? adb shell dumpsys meminfo [-a] [-oom] [-process] com.android.server.am. ActivityManagerService android.app.ActivityThread. android.app.ActivityThread. android.app.ActivityThread. ApplicationThread ApplicationThread ApplicationThread android.os Debug 12th Kandroid Conference - www.kandroid.org 140
  141. 141. How ‘dumpsys meminfo’ works? adb shell dumpsys meminfo [-a] [-oom] [-process] com.android.server.am. ActivityManagerService android.app.ActivityThread. android.app.ActivityThread. android.app.ActivityThread. ApplicationThread ApplicationThread ApplicationThread android.os Debug getNativeHeap*() getMemoryInfo() mallinfo() /proc/<pid>/smaps 12th Kandroid Conference - www.kandroid.org 141
  142. 142. How ‘dumpsys meminfo’ works? android.app.ActivityThread.ApplicationThread.dumpMemInfo() long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.totalMemory() / 1024; long dalvikFree = runtime.freeMemory() / 1024; long dalvikAllocated = dalvikMax - dalvikFree; 12th Kandroid Conference - www.kandroid.org 142
  143. 143. How ‘dumpsys meminfo’ works? android.app.ActivityThread.ApplicationThread.dumpMemInfo() long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.totalMemory() / 1024; long dalvikFree = runtime.freeMemory() / 1024; long dalvikAllocated = dalvikMax - dalvikFree; android.os.Debug.getNativeHeap*() struct mallinfo info = mallinfo(); (jlong) info.usmblks; // Debug.getNativeHeapSize() (jlong) info.uordblks; // Debug.getNativeHeapAllocatedSize() (jlong) info.fordblks; // Debug.getNativeHeapFreeSize() 12th Kandroid Conference - www.kandroid.org 143
  144. 144. How ‘dumpsys meminfo’ works? struct mallinfo { MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE MALLINFO_FIELD_TYPE }; arena; ordblks; smblks; hblks; hblkhd; usmblks; fsmblks; uordblks; fordblks; keepcost; /* /* /* /* /* /* /* /* /* /* non-mmapped space allocated from system */ number of free chunks */ always 0 */ always 0 */ space in mmapped regions */ maximum total allocated space */ always 0 */ total allocated space */ total free space */ releasable (via malloc_trim) space */ bioniclibcupstream-dlmallocmalloc.c 2 4 3 1 ① Total allocated = uordblks ② Total free = fordblks ③ Footprint = uordblks + fordblks ④ Max footprint = usmblks 12th Kandroid Conference - www.kandroid.org 144
  145. 145. Measuring CPU Usage 12th Kandroid Conference - www.kandroid.org 145
  146. 146. Measuring CPU Usage Public android.os.Process android.os.Debug.InstructionCount 12th Kandroid Conference - www.kandroid.org 146
  147. 147. Measuring CPU Usage Public Internal android.os.Process android.os.Debug.InstructionCount com.android.internal.os.ProcessStats 12th Kandroid Conference - www.kandroid.org 147
  148. 148. Measuring CPU Usage Public Internal Android android.os.Process android.os.Debug.InstructionCount com.android.internal.os.ProcessStats adb shell dumpsys cpuinfo 12th Kandroid Conference - www.kandroid.org 148
  149. 149. Measuring CPU Usage Public Internal Android Linux android.os.Process android.os.Debug.InstructionCount com.android.internal.os.ProcessStats adb shell dumpsys cpuinfo adb shell cat /proc/stat adb shell cat /proc/<pid>/stat adb shell top 12th Kandroid Conference - www.kandroid.org 149
  150. 150. Measuring CPU Usage: dumpsys cpuinfo $ adb shell dumpsys cpuinfo Load: 0.0 / 0.01 / 0.05 CPU usage from 27006ms to 5405ms ago: 1.1% 1421/com.android.launcher: 0.3% user + 0.8% kernel / faults: 2187 minor 2.4% 1225/system_server: 0.4% user + 1.9% kernel / faults: 2030 minor 0.1% 949/surfaceflinger: 0% user + 0.1% kernel / faults: 3 minor 0% 952/mediaserver: 0% user + 0% kernel / faults: 8 minor 0% 959/adbd: 0% user + 0% kernel / faults: 11 minor 0% 1295/com.android.systemui: 0% user + 0% kernel / faults: 5 minor +0% 1901/com.example.android.apis: 0% user + 0% kernel 56% TOTAL: 10% user + 45% kernel + 0.7% softirq 12th Kandroid Conference - www.kandroid.org 150
  151. 151. How ‘dumpsys cpuinfo’ works? adb shell dumpsys cpuinfo 12th Kandroid Conference - www.kandroid.org 151
  152. 152. How ‘dumpsys cpuinfo’ works? adb shell dumpsys cpuinfo com.android.server.am. ActivityManagerService 12th Kandroid Conference - www.kandroid.org 152
  153. 153. How ‘dumpsys cpuinfo’ works? adb shell dumpsys cpuinfo com.android.server.am. ActivityManagerService com.android.internal.os ProcessStats 12th Kandroid Conference - www.kandroid.org 153
  154. 154. How ‘dumpsys cpuinfo’ works? adb shell dumpsys cpuinfo com.android.server.am. ActivityManagerService com.android.internal.os ProcessStats com.android.internal.os com.android.internal.os com.android.internal.os ProcessStats.Stats ProcessStats.Stats ProcessStats.Stats 12th Kandroid Conference - www.kandroid.org 154
  155. 155. How ‘dumpsys cpuinfo’ works? adb shell dumpsys cpuinfo com.android.server.am. ActivityManagerService android.os Process com.android.internal.os ProcessStats com.android.internal.os com.android.internal.os com.android.internal.os ProcessStats.Stats ProcessStats.Stats ProcessStats.Stats android_util_ Process.cpp /proc/stat /proc/loadavg /proc/<pid>/stat /proc/<ppid>/task/<pid>/stat 12th Kandroid Conference - www.kandroid.org 155
  156. 156. How ‘dumpsys cpuinfo’ works? procfs (or the proc filesystem) is a special filesystem in UNIXlike operating systems that presents information about processes and other system information in a hierarchical file-like structure, providing a more convenient and standardized method for dynamically accessing process data held in the kernel than traditional tracing methods or direct access to kernel memory. http://en.wikipedia.org/wiki/Procfs 12th Kandroid Conference - www.kandroid.org 156
  157. 157. How ‘dumpsys cpuinfo’ works? procfs (or the proc filesystem) is a special filesystem in UNIXlike operating systems that presents information about processes and other system information in a hierarchical file-like structure, providing a more convenient and standardized method for dynamically accessing process data held in the kernel than traditional tracing methods or direct access to kernel memory. http://en.wikipedia.org/wiki/Procfs http://manpages.courier-mta.org/htmlman5/proc.5.html 12th Kandroid Conference - www.kandroid.org 157
  158. 158. Measuring I/O Usage 12th Kandroid Conference - www.kandroid.org 158
  159. 159. Measuring I/O Usage Public android.net.TrafficStats 12th Kandroid Conference - www.kandroid.org 159
  160. 160. Measuring I/O Usage Public Internal android.net.TrafficStats android.net.NetworkStats android.net.NetworkStatsHistory com.android.internal.net.NetworkStatsFactory 12th Kandroid Conference - www.kandroid.org 160
  161. 161. Measuring I/O Usage Public Internal Android android.net.TrafficStats android.net.NetworkStats android.net.NetworkStatsHistory com.android.internal.net.NetworkStatsFactory adb shell dumpsys netstats adb shell dumpsys diskstats 12th Kandroid Conference - www.kandroid.org 161
  162. 162. Measuring I/O Usage Public Internal Android Linux android.net.TrafficStats android.net.NetworkStats android.net.NetworkStatsHistory com.android.internal.net.NetworkStatsFactory adb shell dumpsys netstats adb shell dumpsys diskstats /proc/net/* 12th Kandroid Conference - www.kandroid.org 162
  163. 163. Measuring Network IO Usage: dumpsys netstats $ adb shell dumpsys netstats Active interfaces: iface=eth0 ident=[[type=MOBILE, subType=COMBINED, subscriberId=310260000000000]] Dev stats: Pending bytes: 43783 History since boot: ident=[[type=MOBILE_HIPRI, subType=COMBINED, subscriberId=310260000000000], [type=MOBILE, subType=COMBINED, subscriberId=310260000000000]] uid=-1 set=ALL tag=0x0 NetworkStatsHistory: bucketDuration=3600000 bucketStart=1382443200000 activeTime=4813 rxBytes=17410 rxPackets=203 txBytes=25579 txPackets=173 operations=0 ... Xt stats: Pending bytes: 37557 History since boot: ident=[[type=MOBILE_HIPRI, subType=COMBINED, subscriberId=310260000000000], [type=MOBILE, subType=COMBINED, subscriberId=310260000000000]] uid=-1 set=ALL tag=0x0 ... UID stats: ... UID tag stats: ... 12th Kandroid Conference - www.kandroid.org 163
  164. 164. How ‘dumpsys netstats’ works? adb shell dumpsys netstats [--full] [--uid] [--tag] 12th Kandroid Conference - www.kandroid.org 164
  165. 165. How ‘dumpsys netstats’ works? adb shell dumpsys netstats [--full] [--uid] [--tag] com.android.server.net. NetworkStatsService 12th Kandroid Conference - www.kandroid.org 165
  166. 166. How ‘dumpsys netstats’ works? adb shell dumpsys netstats [--full] [--uid] [--tag] com.android.server.net. NetworkStatsService com.android.server.net com.android.server.net com.android.server.net NetworkStatsRecorder NetworkStatsRecorder com.android.server.net NetworkStatsRecorder NetworkStatsRecorder 12th Kandroid Conference - www.kandroid.org 166
  167. 167. How ‘dumpsys netstats’ works? adb shell dumpsys netstats [--full] [--uid] [--tag] com.android.server.net. NetworkStatsService com.android.server.net com.android.server.net com.android.server.net NetworkStatsRecorder NetworkStatsRecorder com.android.server.net NetworkStatsRecorder NetworkStatsRecorder com.android.server.net NetworkStatsCollection android.net android.net NetworkStatsHistory android.net NetworkStatsHistory NetworkStatsHistory 12th Kandroid Conference - www.kandroid.org 167
  168. 168. How ‘dumpsys netstats’ works? adb shell dumpsys netstats [--full] [--uid] [--tag] com.android.server NetworkManagementService com.android.server.net. NetworkStatsService com.android.server.net com.android.server.net com.android.server.net NetworkStatsRecorder NetworkStatsRecorder com.android.server.net NetworkStatsRecorder NetworkStatsRecorder com.android.server.net NetworkStatsCollection android.net android.net NetworkStatsHistory android.net NetworkStatsHistory NetworkStatsHistory com.android.internal.net NetworkStatsFactory /proc/net/xt_qtaguid/iface_stat_all /proc/net/xt_qtaguid/iface_stat_fmt /proc/net/xt_qtaguid/stats 12th Kandroid Conference - www.kandroid.org android.net NetworkStats 168
  169. 169. How ‘dumpsys netstats’ works? com.android.server.net.NetworkStatsService.DefaultNetworkStatsSettings @Override public Config getDevConfig() { return new Config(getSecureLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getSecureLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), getSecureLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS)); } @Override public Config getXtConfig() { return getDevConfig(); } @Override public Config getUidConfig() { return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), getSecureLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS), getSecureLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS)); } @Override public Config getUidTagConfig() { return new Config(getSecureLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), getSecureLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS), getSecureLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS)); } 12th Kandroid Conference - www.kandroid.org 169
  170. 170. How ‘dumpsys netstats’ works? Dev: IP + Non IP layer traffic $ adb shell cat /proc/net/xt_qtaguid/iface_stat_all eth0 1 0 0 0 0 220609 3228 2891157 2995 Xt: Only IP layer traffic $ adb shell cat /proc/net/xt_qtaguid/iface_stat_fmt ifname total_skb_rx_bytes total_skb_rx_packets total_skb_tx_bytes total_skb_tx_packets eth0 163781 3231 2846738 2994 Uid: UID level details $ adb shell cat /proc/net/xt_qtaguid/stats idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets 2 eth0 0x0 0 0 163335 3226 2846228 2988 161473 3222 1862 4 0 0 2845850 2982 266 4 112 2 3 eth0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 eth0 0x0 1000 0 819 11 965 12 667 9 152 2 0 0 813 10 152 2 0 0 5 eth0 0x0 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12th Kandroid Conference - www.kandroid.org 170
  171. 171. Measuring Battery Usage 12th Kandroid Conference - www.kandroid.org 171
  172. 172. Measuring Battery Usage Public android.os.BatteryManager 12th Kandroid Conference - www.kandroid.org 172
  173. 173. Measuring Battery Usage Public Internal android.os.BatteryManager android.os.BatteryStats com.android.internal.os.BatteryStatsImpl com.android.internal.os.PowerProfile com.android.server.os.BatteryStatsService 12th Kandroid Conference - www.kandroid.org 173
  174. 174. Measuring Battery Usage Public Internal Android android.os.BatteryManager android.os.BatteryStats com.android.internal.os.BatteryStatsImpl com.android.internal.os.PowerProfile com.android.server.os.BatteryStatsService adb shell dumpsys battery adb shell dumpsys batteryinfo 12th Kandroid Conference - www.kandroid.org 174
  175. 175. Measuring Battery Usage Public Internal Android Linux android.os.BatteryManager android.os.BatteryStats com.android.internal.os.BatteryStatsImpl com.android.internal.os.PowerProfile com.android.server.os.BatteryStatsService adb shell dumpsys battery adb shell dumpsys batteryinfo None (?) 12th Kandroid Conference - www.kandroid.org 175
  176. 176. Measuring Battery Usage: dumpsys batteryinfo $ adb shell dumpsys batteryinfo Battery History: -1d00h43m02s057ms START -1d00h40m00s730ms 050 20080002 status=charging health=good plug=ac temp=0 volt=0 +plugged +sensor brightness=medium -1d00h39m57s332ms 050 60080002 +wake_lock -1d00h39m57s202ms 050 60080302 phone_state=off ... Per-PID Stats: PID 1227 wake time: +3s445ms PID 1227 wake time: +199ms ... Statistics since last charge: System starts: 29, currently on battery: false Time on battery: 0ms (0.0%) realtime, 0ms (0.0%) uptime Total run time: 1d 2h 1m 3s 606ms realtime, 1d 2h 1m 3s 603ms uptime, ... #1000: User activity: 26 other, 27 button, 93 touch Sensor 0: (not used) Apk com.android.keychain: (nothing executed) ... Statistics since last unplugged: Time on battery: 0ms (0.0%) realtime, 0ms (0.0%) uptime ... 12th Kandroid Conference - www.kandroid.org 176
  177. 177. How ‘dumpsys batteryinfo’ works? adb shell dumpsys batteryinfo 12th Kandroid Conference - www.kandroid.org 177
  178. 178. How ‘dumpsys batteryinfo’ works? adb shell dumpsys batteryinfo com.android.server.am. BatteryStatsService 12th Kandroid Conference - www.kandroid.org 178
  179. 179. How ‘dumpsys batteryinfo’ works? adb shell dumpsys batteryinfo com.android.server.am. BatteryStatsService com.android.internal.os BatteryStatsImpl 12th Kandroid Conference - www.kandroid.org 179
  180. 180. How ‘dumpsys batteryinfo’ works? adb shell dumpsys batteryinfo com.android.server.am. BatteryStatsService com.android.internal.os BatteryStatsImpl android.os BatteryStats 12th Kandroid Conference - www.kandroid.org 180
  181. 181. How ‘dumpsys batteryinfo’ works? adb shell dumpsys batteryinfo com.android.server.am. BatteryStatsService com.android.internal.os BatteryStatsImpl android.os BatteryStats noteBluetoothOff() noteBluetoothOn() noteFullWifiLockAcquired(int) noteFullWifiLockAcquiredFromSource(WorkSource) noteFullWifiLockReleased(int) noteFullWifiLockReleasedFromSource(WorkSource) noteInputEvent() noteNetworkInterfaceType(String, int) notePhoneDataConnectionState(int, boolean) notePhoneOff() notePhoneOn() notePhoneSignalStrength(SignalStrength) notePhoneState(int) noteScreenBrightness(int) noteScreenOff() noteScreenOn() ... noteWifiScanStarted(int) noteWifiScanStartedFromSource(WorkSource) noteWifiScanStopped(int) noteWifiScanStoppedFromSource(WorkSource) noteWifiStopped(WorkSource) 12th Kandroid Conference - www.kandroid.org 181
  182. 182. If you can’t automate the measurement of it, it is difficult to improve it. 12th Kandroid Conference - www.kandroid.org 182
  183. 183. If you can’t automate the measurement of it, it is difficult to improve it. If you can’t understand the measurement results, it is impossible to improve it. 12th Kandroid Conference - www.kandroid.org 183

×