This document primarily covers micro-optimizations that can improve overall app performance
when combined, but it's unlikely that these changes will result in dramatic
performance effects. Choosing the right algorithms and data structures should always be your
priority, but is outside the scope of this document. You should use the tips in this document
as general coding practices that you can incorporate into your habits for general code
efficiency.

There are two basic rules for writing efficient code:

Don't do work that you don't need to do.

Don't allocate memory if you can avoid it.

One of the trickiest problems you'll face when micro-optimizing an Android
app is that your app is certain to be running on multiple types of
hardware. Different versions of the VM running on different
processors running at different speeds. It's not even generally the case
that you can simply say "device X is a factor F faster/slower than device Y",
and scale your results from one device to others. In particular, measurement
on the emulator tells you very little about performance on any device. There
are also huge differences between devices with and without a
JIT: the best
code for a device with a JIT is not always the best code for a device
without.

To ensure your app performs well across a wide variety of devices, ensure
your code is efficient at all levels and aggressively optimize your performance.

Avoid Creating Unnecessary Objects

Object creation is never free. A generational garbage collector with per-thread allocation
pools for temporary objects can make allocation cheaper, but allocating memory
is always more expensive than not allocating memory.

As you allocate more objects in your app, you will force a periodic
garbage collection, creating little "hiccups" in the user experience. The
concurrent garbage collector introduced in Android 2.3 helps, but unnecessary work
should always be avoided.

Thus, you should avoid creating object instances you don't need to. Some
examples of things that can help:

If you have a method returning a string, and you know that its result
will always be appended to a StringBuffer anyway, change your signature
and implementation so that the function does the append directly,
instead of creating a short-lived temporary object.

When extracting strings from a set of input data, try
to return a substring of the original data, instead of creating a copy.
You will create a new String object, but it will share the char[]
with the data. (The trade-off being that if you're only using a small
part of the original input, you'll be keeping it all around in memory
anyway if you go this route.)

A somewhat more radical idea is to slice up multidimensional arrays into
parallel single one-dimension arrays:

An array of ints is a much better than an array of Integer
objects,
but this also generalizes to the fact that two parallel arrays of ints
are also a lot more efficient than an array of (int,int)
objects. The same goes for any combination of primitive types.

If you need to implement a container that stores tuples of (Foo,Bar)
objects, try to remember that two parallel Foo[] and Bar[] arrays are
generally much better than a single array of custom (Foo,Bar) objects.
(The exception to this, of course, is when you're designing an API for
other code to access. In those cases, it's usually better to make a small
compromise to the speed in order to achieve a good API design. But in your own internal
code, you should try and be as efficient as possible.)

Prefer Static Over Virtual

If you don't need to access an object's fields, make your method static.
Invocations will be about 15%-20% faster.
It's also good practice, because you can tell from the method
signature that calling the method can't alter the object's state.

Use Static Final For Constants

Consider the following declaration at the top of a class:

static int intVal = 42;
static String strVal = "Hello, world!";

The compiler generates a class initializer method, called
<clinit>, that is executed when the class is first used.
The method stores the value 42 into intVal, and extracts a
reference from the classfile string constant table for strVal.
When these values are referenced later on, they are accessed with field
lookups.

The class no longer requires a <clinit> method,
because the constants go into static field initializers in the dex file.
Code that refers to intVal will use
the integer value 42 directly, and accesses to strVal will
use a relatively inexpensive "string constant" instruction instead of a
field lookup.

Note: This optimization applies only to primitive types and
String constants, not arbitrary reference types. Still, it's good
practice to declare constants static final whenever possible.

Use Enhanced For Loop Syntax

The enhanced for loop (also sometimes known as "for-each" loop) can be used
for collections that implement the Iterable interface and for arrays.
With collections, an iterator is allocated to make interface calls
to hasNext() and next(). With an ArrayList,
a hand-written counted loop is
about 3x faster (with or without JIT), but for other collections the enhanced
for loop syntax will be exactly equivalent to explicit iterator usage.

What's important here is that we define a private inner class
(Foo$Inner) that directly accesses a private method and a private
instance field in the outer class. This is legal, and the code prints "Value is
27" as expected.

The problem is that the VM considers direct access to Foo's
private members from Foo$Inner to be illegal because
Foo and Foo$Inner are different classes, even though
the Java language allows an inner class to access an outer class' private
members. To bridge the gap, the compiler generates a couple of synthetic
methods:

The inner class code calls these static methods whenever it needs to
access the mValue field or invoke the doStuff() method
in the outer class. What this means is that the code above really boils down to
a case where you're accessing member fields through accessor methods.
Earlier we talked about how accessors are slower than direct field
accesses, so this is an example of a certain language idiom resulting in an
"invisible" performance hit.

If you're using code like this in a performance hotspot, you can avoid the
overhead by declaring fields and methods accessed by inner classes to have
package access, rather than private access. Unfortunately this means the fields
can be accessed directly by other classes in the same package, so you shouldn't
use this in public API.

Avoid Using Floating-Point

As a rule of thumb, floating-point is about 2x slower than integer on
Android-powered devices.

In speed terms, there's no difference between float and
double on the more modern hardware. Space-wise, double
is 2x larger. As with desktop machines, assuming space isn't an issue, you
should prefer double to float.

Also, even for integers, some processors have hardware multiply but lack
hardware divide. In such cases, integer division and modulus operations are
performed in software—something to think about if you're designing a
hash table or doing lots of math.

Know and Use the Libraries

In addition to all the usual reasons to prefer library code over rolling
your own, bear in mind that the system is at liberty to replace calls
to library methods with hand-coded assembler, which may be better than the
best code the JIT can produce for the equivalent Java. The typical example
here is String.indexOf() and
related APIs, which Dalvik replaces with
an inlined intrinsic. Similarly, the System.arraycopy() method
is about 9x faster than a hand-coded loop on a Nexus One with the JIT.

Tip:
Also see Josh Bloch's Effective Java, item 47.

Use Native Methods Carefully

Developing your app with native code using the
Android NDK
isn't necessarily more efficient than programming with the
Java language. For one thing,
there's a cost associated with the Java-native transition, and the JIT can't
optimize across these boundaries. If you're allocating native resources (memory
on the native heap, file descriptors, or whatever), it can be significantly
more difficult to arrange timely collection of these resources. You also
need to compile your code for each architecture you wish to run on (rather
than rely on it having a JIT). You may even have to compile multiple versions
for what you consider the same architecture: native code compiled for the ARM
processor in the G1 can't take full advantage of the ARM in the Nexus One, and
code compiled for the ARM in the Nexus One won't run on the ARM in the G1.

Native code is primarily useful when you have an existing native codebase
that you want to port to Android, not for "speeding up" parts of your Android app
written with the Java language.

Performance Myths

On devices without a JIT, it is true that invoking methods via a
variable with an exact type rather than an interface is slightly more
efficient. (So, for example, it was cheaper to invoke methods on a
HashMap map than a Map map, even though in both
cases the map was a HashMap.) It was not the case that this
was 2x slower; the actual difference was more like 6% slower. Furthermore,
the JIT makes the two effectively indistinguishable.

On devices without a JIT, caching field accesses is about 20% faster than
repeatedly accessing the field. With a JIT, field access costs about the same
as local access, so this isn't a worthwhile optimization unless you feel it
makes your code easier to read. (This is true of final, static, and static
final fields too.)

Always Measure

Before you start optimizing, make sure you have a problem that you
need to solve. Make sure you can accurately measure your existing performance,
or you won't be able to measure the benefit of the alternatives you try.

You may also find
Traceview useful
for profiling, but it's important to realize that it currently disables the JIT,
which may cause it to misattribute time to code that the JIT may be able to win
back. It's especially important after making changes suggested by Traceview
data to ensure that the resulting code actually runs faster when run without
Traceview.

For more help profiling and debugging your apps, see the following documents: