Performance Design for running Android applications

Source: Internet
Author: User
Tags integer division

Mobile devices running Android applications are limited by their computing capabilities, storage space, and battery life. Therefore, it must be efficient. Battery life may be a reason for your optimization, even if it seems to be running fast enough. Because of the importance of endurance to users, when the power consumption increases sharply, it means that the user will find out sooner or later because of your program.

Although this document mainly contains minor optimizations, these cannot be the key to your software's success or failure. Choosing an appropriate algorithm and data structure is always the first thing you should consider, but this is beyond the scope of this document.

1. Introduction

There are two basic principles for writing efficient code:

◆ No unnecessary work

◆ Avoid memory allocation whenever possible.

2. Smart Optimization

This document is about minor optimizations to the Android specification. First, make sure that you understand the code to be optimized and know how to measure the effect (good or bad) of your modifications ). Investment and Development time is limited, so wise time planning is very important.

This document also ensures that you make the best choice on algorithms and data structures while considering the potential impact of API selection. Using appropriate data structures and algorithms is more valuable than any suggestions here. Considering the impact of API versions, you can choose a better implementation.

A tricky problem you may encounter when optimizing your Android program is to ensure that your program runs on different hardware platforms. Virtual machines of different versions run at different speeds on different processors. In addition, device A is not A simple device that is faster or slower than Device B and is arranged between A device and other devices. In particular, the simulator can only evaluate a small part of things that can be reflected on the device. There is also a huge difference between devices with or without JIT: code with JIT devices is sometimes not the best for devices without JIT.

If you want to know the performance of the Program on the device, you must test it on it.

3. Avoid creating unnecessary objects

Object creation will never be free. The generation GC of each thread assigns an address pool to the temporary object to reduce the allocation overhead. However, the memory allocation cost is usually higher than the memory allocation.

If an object is allocated within the user interface period, a periodic garbage collection will be forced, causing a small pause gap for the user experience. The concurrent collection introduced in Gingerbread may be useful, but unnecessary work should be avoided.

Therefore, avoid creating unnecessary object instances. The following are examples:

◆ If a method returns a String, its return value is usually appended to a StringBuffer, changing the declaration and implementation, so that the function is directly appended to it, instead of creating a temporary variable that temporarily exists.

◆ When reading data from the input dataset, consider returning the child string of the original data instead of creating a new copy. In this way, you will create a new object, but they share the char array of the data. In exchange, even if you only use a portion of the original input, you must ensure that it remains in the memory.

A more thorough idea is to cut multi-dimensional arrays into one-dimensional arrays:

◆ Arrays of the Int type are better than those of the Integer type. By extension, two parallel int arrays are more efficient than an (int, int) object array. This theorem is applicable to any combination of basic data types.

◆ If you need to implement the container for storing the tuples (Foo, Bar) object, remember that the two parallel arrays Foo [] and Bar [] are better than the arrays of one (Foo, Bar) object. (Exception: when you design an API to call other code, you 'd better use the API design in exchange for a small speed increase. But try to implement it efficiently in your internal code .)

Generally, try to avoid creating short-term temporary objects. Small object creation means low-frequency garbage collection. This has a direct impact on the user experience.

4. Performance puzzles

The document of the previous version provides a lot of misleading ideas. Here we will clarify some of them:

◆ On devices without JIT, it is more effective to use the specific type of the object passed by the call method instead of the interface type (for example, passing a HashMap map is less costly than passing a Map map to call a method, even though the map in both cases is HashMap ). However, this is not a two-fold slow situation. In fact, the difference is only 6%, while JIT makes the two calls less efficient.

◆ On devices without JIT, the cached access field is about 20% faster than the directly accessed field. In the case of JIT, field access and local access consume the same. So it is not worth optimization, unless you think it will make your code easier to read (for final, static, and static final variables ).

5. Use static instead of virtual

If you do not need to access the field of an object and set the method to static, the call will be accelerated by 15% to 20%. This is also a good practice, because you can use the method declaration to know that calling this method does not need to update the status of this object.

6. Avoid internal Getters/Setters

In the source language like C ++, the common practice is to use Getters (I = getCount () instead of directly accessing the field (I = mCount ). This is a good habit in C ++, because the compiler will inline These accesses. If you need to restrict or debug access to these domains, you can add code at any time.

In Android, this is a bad idea. Virtual method calls are much more expensive than directly accessing fields. There is a reason to use Getters and Setters in public interfaces according to the common object-oriented language approach, but direct access should be adopted in a class that frequently accesses its fields.

When there is no JIT, direct field access is about three times faster than getter, which is irrelevant to the call. With JIT (the overhead of directly accessing fields is the same as that of accessing local variables), it is 7 times faster. This is true in Froyo, but the inline of the Getter method will be improved in JIT later.

7. Use the Static Final modifier for Constants

Consider the following statement:

Static int intVal = 42;

Static String strVal = "Hello, world! ";

The compiler generates a class initialization method named clinit. When the class is used for the first time, this method will save 42 to intVal and obtain the reference of the class String constant strVal. When these values are referenced later, they are accessed through field searches.

We improved the implementation by using the final Keyword:

Static final int intVal = 42;

Static final String strVal = "Hello, world! ";

The class no longer requires the clinit method, because the constant enters the static field initializer In the dex file. REFERENCE The intVal code and directly call the integer value 42. when accessing strVal, The string constant command with a relatively low overhead replaces the field search. (This optimization only applies to constants of the basic data type and String type, rather than any reference type. But it is a good practice to declare constants as static final type as much as possible.

8. Use the improved For loop syntax

The improved for loop (sometimes called for-each loop) can be used in collection classes and arrays that implement the iterable interface. In the collection class, the iterator prompts the interface to access the hasNext () and next () methods. In the ArrayList, the Count loop iteration is three times faster (no matter whether JIT exists), but in other collection classes, the improved for loop syntax has the same efficiency as the iterator.

Here are some implementation of iterative Arrays: static class Foo {

Int mSplat;

}

Foo [] mArray =...

Public void zero (){

Int sum = 0;

For (int I = 0; I mArray. length; ++ I ){

Sum + = mArray. mSplat;

}

}

Public void one (){

Int sum = 0;

Foo [] localArray = mArray;

Int len = localArray. length;

For (int I = 0; I len; ++ I ){

Sum + = localArray. mSplat;

}

}

Public void two (){

Int sum = 0;

For (Foo a: mArray ){

Sum + = a. mSplat;

}

}

Zero () is the slowest, because for previous iterations in this traversal, JIT cannot optimize the overhead for obtaining the array length.

One () is faster. It puts everything into local variables to avoid searching. However, only the array length promotes performance improvement.

Two () is the fastest running on devices without JIT. For devices with JIT, it is not the same as one. He used the improved for loop syntax in JDK1.5.

Conclusion: The improved for loop is preferred, but the handwritten counting loop is considered in ArrayList iteration with demanding performance.

9. In the private interior, consider replacing the private access permission with the package access permission

Consider the following definition: public class Foo {

Private class Inner {

Void stuff (){

Foo. this. doStuff (Foo. this. mValue );

}

}

Private int mValue;

Public void run (){

Inner in = new Inner ();

MValue = 27;

In. stuff ();

}

Private void doStuff (int value ){

System. out. println ("Value is" + value );

}

}

The key to note is that the defined private internal class (Foo $ Inner) directly accesses a private method and private variable in the external class. This is legal, and the code will print out the expected Value is 27.

But the problem is that the virtual machine deems it illegal to directly access the private members of Foo From Foo $ Inner because they are two different classes, although the Java language allows internal classes to access private members of external classes, the compiler generates several comprehensive methods to bridge these gaps.

Java code

Static int Foo. access $100 (Foo foo ){

Return foo. mValue;

}

Static void Foo. access $200 (Foo foo, int value ){

Foo. doStuff (value );

}

The internal class calls these static methods wherever the mValue field or doStuff method needs to be accessed in the external class. This means that the Code will directly access the member variable to be accessed through the accessor method. As mentioned earlier, the access speed of accessors is slower than that of direct access. This example shows that some language conventions cause invisible performance problems.

If you use this code in high-performance hot spot, you can declare fields and members accessed by internal classes as package access permissions rather than private ones. Unfortunately, this means that these fields will be accessed by other classes in the same package, so they are not suitable for public APIs.

10. make proper use of Floating Point Numbers

Generally, in Android devices, floating point numbers are twice slower than integer types, or in JIT G1 and Nexus One with FPU and JIT (the absolute speed difference between the two devices is about 10 times ).

In terms of speed, float and double are not different in modern hardware. More broadly, double is about double. In a desktop machine that has no storage space problems, double has a higher priority than float.

However, even an integer type, some chips have hardware multiplication, but division is not required. In this case, integer division and modulo calculation are implemented by software. Consider when designing a Hash table or doing a lot of arithmetic operations.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.