In this blog, We will learn some android performance tips that how to manage memory, where to use the static and some good loop practices.
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 is 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
int
s is a much better than an array ofInteger
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 parallelFoo[]
andBar[]
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.)
Generally speaking, avoid creating short-term temporary objects if you can. Fewer objects created mean less-frequent garbage collection, which has a direct impact on user experience.
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,
1 2 |
static int intVal = 42; static String strVal = "Hello, world!"; |
The compiler generates a class initializer method, called, that is executed when the class is first used. The method stores the value 42 into intVal
and extracts a reference from the class file string constant table for strVal
. When these values are referenced later on, they are accessed with field lookups.
We can improve matters with the “final” keyword:
1 2 |
static final int intVal = 42; static final String strVal = "Hello, world!"; |
The class no longer requires a <clinit>
the 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.
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.
There are several alternatives for iterating through an array:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
static class Foo { int splat; } Foo[] array = ... public void zero() { int sum = 0; for (int i = 0; i < array.length; ++i) { sum += array[i].splat; } } public void one() { int sum = 0; Foo[] localArray = array; int len = localArray.length; for (int i = 0; i < len; ++i) { sum += localArray[i].splat; } } public void two() { int sum = 0; for (Foo a : array) { sum += a.splat; } } |
zero()
is slowest, because the JIT can’t yet optimize away the cost of getting the array length once for every iteration through the loop.
one()
is faster. It pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit.
two()
is fastest for devices without a JIT, and indistinguishable from one() for devices with a JIT. It uses the enhanced for loop syntax introduced in version 1.5 of the Java programming language.
I hope this blog is useful to you. Thanks for reading.
Stay Cool And Stay Updated!!!
Reference: https://developer.android.com/