Support free tutorials









vogella training Training Books



Android application (performance and more) analysis tools - Tutorial

Lars Vogel

Version 2.3

14.08.2013

Analyzing Android performance issues

This tutorial describes the available tools in Android to perform a performance analysis of Android applications. It is based on Eclipse 4.2, Java 1.6 and Android 4.2.


Table of Contents

1. Overview
2. Android Basics
3. StrictMode
4. Developer Settings
5. Lint
6. Exercise: Lint
7. Traceview
7.1. Introduction
7.2. Using Traceview in Eclipse
7.3. Using TraceView from the command line
8. Exercise: Traceview
8.1. Create example project
8.2. Perform trace
8.3. Solve performance problems
9. Hierarchy Viewer
10. Exercise: Hierarchy Viewer
11. Layout optimization
12. Memory Dumps
13. Systrace
14. Pixel Perfect perspective
15. Simulating pixel density
16. Android templates
17. Profile GPU rendering
18. Analyzing Overdraw
19. Support this website
19.1. Thank you
19.2. Questions and Discussion
20. Links and Literature
20.1. Source Code
20.2. Android Animation Resources
20.3. vogella Resources

1. Overview

It is very important for Android applications to perform all operations as fast as possible. This description lists the available tools to trace and optimize your Android application.

2. Android Basics

The following assumes that you have already basic knowledge in Android development. Please check the Android development tutorial to learn the basics.

3. StrictMode

You should avoid performing long running operations on the UI thread. This includes file and network access.

To ensure this you can use StrictMode. StrictMode is available as of API 9 (Android 2.3.3) and allows to setup thread policies for your application.

Via StrictMode you can instruct the Android system to crash your application if it performs long running operations, e.g. I/O in the user interface thread.

The following code shows how to use StrictMode. As the activity violates these settings it will crash.

package de.vogella.android.strictmode;

import java.io.BufferedWriter;
import java.io.OutputStreamWriter;

import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;

public class TestStrictMode extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Activate StrictMode
    StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
        .detectAll()
        .detectDiskReads()
        .detectDiskWrites()
        .detectNetwork() 
         // alternatively .detectAll() for all detectable problems
        .penaltyLog()
        .penaltyDeath()
        .build());
    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
         .detectLeakedSqlLiteObjects()
         .detectLeakedClosableObjects()
        // alternatively .detectAll() for all detectable problems
        .penaltyLog()
        .penaltyDeath()
        .build());
    
    // Test code
    setContentView(R.layout.main);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    String eol = System.getProperty("line.separator");
    try {
      BufferedWriter writer = 
          new BufferedWriter(new OutputStreamWriter(openFileOutput("myfile", 
              MODE_WORLD_WRITEABLE)));
      writer.write("This is a test1." + eol);
      writer.write("This is a test2." + eol);
      writer.write("This is a test3." + eol);
      writer.write("This is a test4." + eol);
      writer.write("This is a test5." + eol);
      writer.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
} 

StrictMode should only be used during development and not in your live application.

4. Developer Settings

Developer Settings in your Setting application of your Android phone allow to set configurations which simplify the analysis of your application. For example you can enable that the touch area is highlighted.

If you have a Android 4.2 phone, try going to the About section in the Settings and tap the Build number entry 7 times.

If you phone does not have this option try using an emulator.

In some cases you need to restart the application to make the setting work.

5. Lint

The Android lint tool is a static code analysis tool for Android applications. It provides command line and Eclipse supported checks for potential bugs and optimization improvements for Android applications.

Some checks are performed by default in Eclipse. To run active Lint checks in Eclipse on your Android application, right-click on your project and select Android ToolsRun Lint: Check for Common Errors.

You see the generated warnings in the Lint Warning view .

In the Eclipse Preferences you can configure the Lint checks under WindowPreferencesAndroidLint Error Checking.

You can run link also from the command line.

# run lint check for myproject
lint myproject 

6. Exercise: Lint

Run a full lint check on a project of your choice. Try to solve all errors and warnings.

7. Traceview

7.1. Introduction

Traceview is a graphical viewer to see logs created by an Android application. Via Traceview you can measure the performance of your application to identify performance problems.

Traceview is located as standalone tool in the tools folder of your Android SDK installation folder and it also integrated into Eclipse via the Android Developer Tools (ADT).

7.2. Using Traceview in Eclipse

Eclipse supports tracing directly in the DDMS perspective.

To start tracing an application select your application process in the Devices view and select the Start Method Profiling button as depicted in the following screenshot.

Use your application and re-press the same button to stop profiling. This will open a new editor which shows you the tracing results.

You can zoom into the graphic to get more details. To zoom out, double-click on the time line.

7.3. Using TraceView from the command line

To start tracing some code put the following code snippet around it.

android.os.Debug.startMethodTracing("yourstring");

// ... your code is here

android.os.Debug.stopMethodTracing(); 

The parameter "yourstring" tells the system that it should store the data under "/sdcard/yourstring.trace". To save data on the sdcard your application needs the WRITE_EXTERNAL_STORAGE permission. After running your application you can copy the results from the device via the adb command line tool.

adb pull /sdcard/yourstring.trace
traceview yourstring 

This will start Traceview which allow you to analyze your performance data via a graphical way. The DDMS view has also a trace button available. This will trace the running application and does not require an additional authorization.

8. Exercise: Traceview

8.1. Create example project

Create an Android application with the top level package called com.vogella.android.traceview.

Add the following key to your values/strings.xml file.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Traceview Example</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="number_template"><b>Random number: %1$s</b></string>

</resources> 

Create the following layout file called rowlayout.xml.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:orientation="horizontal" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Entry"
                android:textAppearance="?android:attr/textAppearanceListItem" />

            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Stub"
                android:textAppearance="?android:attr/textAppearanceListItemSmall" />
        </LinearLayout>
    </LinearLayout>

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="10dp"
        android:layout_height="?android:attr/listPreferredItemHeight"
        android:background="@android:color/black" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</LinearLayout> 

Implement the following adapter for your ListView.

package com.vogella.android.traceview;

import java.util.Collections;
import java.util.List;

import android.content.Context;
import android.content.res.Resources;
import android.os.Debug;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class MyArrayAdapter extends ArrayAdapter<String> {

  private List<String> values;
  private Context context;

  public MyArrayAdapter(Context context, List<String> values) {
    super(context, R.layout.rowlayout);
    this.context = context;
    this.values = values;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    Debug.startMethodTracing("getViewOfTrace");
    // Ensure sorted values
    Collections.sort(values);
    LayoutInflater inflater = (LayoutInflater) context
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.rowlayout, parent, false);
    Resources res = context.getResources();
    String text = String.format(res.getString(R.string.number_template),
        values.get(position));
    CharSequence styledText = Html.fromHtml(text);
    TextView textView = (TextView) view.findViewById(R.id.textView3);
    textView.setText(styledText);
    Debug.stopMethodTracing();
    return view;
  }
} 

Implement a ListView in the activity which shows 1000 random generated strings.

package com.vogella.android.traceview;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

import android.app.ListActivity;
import android.os.Bundle;

public class MainActivity extends ListActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    List<String> list = createValues();
    MyArrayAdapter adapter = new MyArrayAdapter(this, list);
    setListAdapter(adapter);
  }

  private static List<String> createValues() {
    SecureRandom random = new SecureRandom();
    List<String> list = new ArrayList<String>();
    for (int i = 0; i < 1000; i++) {
      String string = new BigInteger(130, random).toString(32);
      list.add(string);
    }
    return list;
  }

} 

Add the permission to write on external storage to your application.

8.2. Perform trace

Run your application. Afterwards connect to your device via adb and copy the resulting performance trace to your drive. Analyze the result.

8.3. Solve performance problems

Improve the performance based on the measurements of Traceview. Here are some pointers what to improve.

  • Replace the bold styling in the getView() method with the corresponding android:textStyle="bold attribute in your layout to avoid the Html.fromHtml() call.

  • Move the sorting to another place

  • Reuse convertView in your Adapter, if not null

  • Avoid the findViewById() method call by using the HolderPattern in your ListView

Note

The layout is also not optimized. We reuse this exercise in the exercise for the HierarchyView

9. Hierarchy Viewer

The Hierarchy View perspective allows you to visualize the View hierarchy of your Android application and helps you to identify unnecessary layers in this hierarchy.

You can open the Hierarchy View via WindowOpen PerspectiveOther...Hierarchy View

In the Windows view you can select the process for which you want to analyze the view hierarchy.

Hierarchy Viewer for selecting the process

The currently active layout is analyzed and displayed.

Hierarchy Viewer

The Tree View view show three light bulbs for the views. The first one indicates the time for calculating the size of the view, the second one indicates the time for creating the layout and the third one for drawing the view. Performance intensive work is indicated with the yellow or red color.

10. Exercise: Hierarchy Viewer

Continue to use the same example as in Section 8.1, “Create example project”. Open the Hierarchy View perspective and analyze the view layer.

While none of these layout layers is very performance intensive it contains redundant layers and unnecessary views. Remove the unnecessary view layers.

11. Layout optimization

You should optimize your layout. The following gives an example how to use FrameLayout with an ImageView and one TextView to create result despicted in the next screenshot. It uses the possibility to position the TextView in the layout and to style parts of its text content differently.

Styling TextView with TextAppearanceSpan

Create a project called com.vogella.android.textview.spannablestring.

Add two news styles to your styles.xml file.

<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a API-level are here. -->
    </style>

    <style name="textHeader">
        <item name="android:padding">4dip</item>
        <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
        <item name="android:textColor">#000000</item>
        <item name="android:fontFamily">sans-serif-condensed</item>
    </style>

    <style name="textbody">
        <item name="android:padding">4dip</item>
        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">#c0c0c0</item>
    </style>

</resources> 

Create the following layout.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/FrameLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/input"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_margin="16dp"
        android:text="@string/hello_world"
        android:textSize="32sp" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="image"
        android:src="@drawable/vogella" />

</FrameLayout> 

Style your text in the TextView via separate TextAppearanceSpan as demonstrated in the following code.

package com.vogella.android.textview.spannablestring;

import android.app.Activity;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.TextAppearanceSpan;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    TextView textView = (TextView) findViewById(R.id.input);
    String header = "This is the header";
    String description = "This is the description";

    Spannable styledText = new SpannableString(header + "\n" + description);
    TextAppearanceSpan span1 = new TextAppearanceSpan(this,
        R.style.textHeader);
    TextAppearanceSpan span2 = new TextAppearanceSpan(this,
        R.style.textbody);
    styledText.setSpan(span1, 0, header.length(),
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    styledText.setSpan(span2, header.length() + 1, header.length() + 1
        + description.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(styledText);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }

} 

The resulting layout is much faster than a layout based on RelativeLayout. Also HTML styling was avoid as the HTML parser is relatively expensive.

12. Memory Dumps

You can create a memory snapshot and analyze it with the Eclipse Memory Analyzer.

13. Systrace

Systrace allows to measure the performance directly at kernel level. To enable systrace, select the Developer options and select the Enable traces entry. In the next dialog you can define what type of events should be profiled, e.g. Graphics and View.

Enable traces

Enable traces, select Graphics and View

To use systrace, open a terminal and run systrace.py from the android_sdk_installdir/tools/systrace directory. You may have to set it to executable (chmod 777 systrace.py on Linux).

You can also start Systrace directly from Eclipse via the DDMS perspective.

Systrace with ADT Part 1

Systrace with ADT Part 2

Systrace captures events for 5 seconds. As result Systrace creates a HTML file which allows you to analyze potential issues.

14. Pixel Perfect perspective

Not performance related but still useful is the Pixel Perfect perspective which allow to display the screen of the currently running application on the emulator or device and magnify the image of that screen.

15. Simulating pixel density

You can use the command line to simulate different device densities and display resolutions.

This allows you to use a device with a high device density and resolution to simulate other devices.

// Set the display size
adb shell am display-size 600x800

// Set the display density
adb shell am display-density 80 

16. Android templates

You can define your own templates for the Android project creation wizard. See the following links for more information.

Roman Nurik: https://plus.google.com/113735310430199015092/posts/XTKTamk4As8

Official documentation: https://dl.dropbox.com/u/231329/android/templatedocs/index.html

Additional code templates - https://github.com/jgilfelt/android-adt-templates

17. Profile GPU rendering

In the Developer options in the Setting or your Android device you can activate Profile GPU rendering. With this option the system tracks the time it took to draw the last 128 frames.

After activating this and restarting your application you can get the information via the following command.

adb shell dumpsys gfxinfo your_package 

To measure the frame rate of your application, e.g. by scrolling on a list view. In most cases you need to interact with your application to trigger that it re-draws itself.

In the resulting log, look for a section called Profile data in ms.

18. Analyzing Overdraw

Overdraw happens if you draw something on top of something else. For example an activity has a Window as background. If a TextView it added to the application, the TextView is drawn on top of the Window.

Overdrawn is therefore intended to happen. But unnecessary overdraw should be avoid to have the best performance possible.

Unnecessary overdraw can be caused by complex view hierarchies. In general a 2x overdraw (a pixel gets drawn three times) is standard and expected but more should be avoided.

You can enable a visualization of overdraw via the Development Settings with the Show GPU overdraw setting. This section adds colors to your screen based on the number of overdraws. The following table explains the used color schema.

Table 1. Overdrawn colors

Color Meaning
No color No overdraw
Blue 1x overdraw, pixel was painted twice
Green 2x
Light red 3x, might indicate a problem, small red areas are still ok
Dark red 4x, pixel was pained 5 times or more, indicates a problem.


After visualization of potential problematic areas, you can analyze your View hierarchy with the Hierarchy Viewer.

19. Support this website

This tutorial is Open Content under the CC BY-NC-SA 3.0 DE license. Source code in this tutorial is distributed under the Eclipse Public License. See the vogella License page for details on the terms of reuse.

Writing and updating these tutorials is a lot of work. If this free community service was helpful, you can support the cause by giving a tip as well as reporting typos and factual errors.

19.1. Thank you

Please consider a contribution if this article helped you. It will help to maintain our content and our Open Source activities.

19.2. Questions and Discussion

If you find errors in this tutorial, please notify me (see the top of the page). Please note that due to the high volume of feedback I receive, I cannot answer questions to your implementation. Ensure you have read the vogella FAQ as I don't respond to questions already answered there.

20. Links and Literature

20.1. Source Code

Source Code of Examples

20.2. Android Animation Resources

Traveview homepage

20.3. vogella Resources

vogella Training Android and Eclipse Training from the vogella team

Android Tutorial Introduction to Android Programming

GWT Tutorial Program in Java, compile to JavaScript and HTML

Eclipse RCP Tutorial Create native applications in Java

JUnit Tutorial Test your application

Git Tutorial Put all your files in a distributed version control system