Performance design for Android application running

Source: Internet
Author: User
Tags arithmetic array length arrays final garbage collection integer integer division static class


Android applications run on mobile devices that are limited by their computing power, storage space, and battery endurance. From this, it must be efficient. Battery Endurance may be a reason for you to optimize your program, even if it seems to be running fast enough. Because of the importance of endurance to the user, when the power consumption is soaring, it means that the user will sooner or later find it is due to your program.



While this document contains a few minor optimizations, these must not be the key to your software's success or failure. Choosing the right algorithm and data structure is always the first thing you should consider, but this is beyond the scope of this document.



1. Introduce



There are two basic principles for writing efficient code:



Do not do the necessary work



Try to avoid memory allocations.



2. Intelligent optimization



This document is about micro-optimization of the Android specification, so make sure you know what code needs to be optimized and how to measure the effect (good or bad) of your changes. The time spent on investment development is limited, so sensible time planning is important.



This document also ensures that you make the best choice in algorithms and data structures, taking into account the potential impact of API choices. Using the right data structure and algorithms is more valuable than any of the recommendations here, and considering the impact of the API version will be the true choice for you to implement better.



A tricky problem when you optimize your Android program is to make sure your program runs on a different hardware platform. Different versions of virtual machines run at different speeds on a variety of processors. And not simple device A is faster or slower than device B, and arranges between one device and other devices. In particular, the simulator can only evaluate a small part of what is available on the device. There is also a huge difference between the devices that have JIT: the code that has good JIT equipment is sometimes not the best device for JIT-free devices.



If you want to know how the program behaves on the device, you have to test it on it.



3. Avoid creating unnecessary objects



Object creation will never be free. The generational GC of each thread allocates an address pool to a temporary object to reduce the allocation overhead, but allocating memory often requires a higher cost than not allocating memory.



If objects are allocated within the user interface cycle, a periodic garbage collection is enforced, creating a small pause gap for the user experience. The concurrent recycling described in gingerbread may be useful, but you should avoid unnecessary work.



Therefore, avoid creating an unwanted object instance. Here are a few examples:



If there is a method that returns a string, his return value is usually appended to a stringbuffer, changing the declaration and implementation, so that the function attaches directly behind it, rather than creating a transient temporary variable.



When reading data from the input , consider returning the substring of the original data rather than creating a new copy. So you create a new object, but they share a char array of that data. In exchange, even if you only use a part of the original input, you also need to ensure that it always exists in memory.



A more thorough view is to cut multidimensional arrays into one-dimensional arrays:



An array of type int is better than an integer type. By extension, two parallel arrays of int are more efficient than a (Int,int) type of object array. This theorem is common to any combination of basic data types.



If you need to implement a container that holds a tuple (Foo,bar) object, remember that two parallel arrays foo[], bar[] is better than an array of (Foo,bar) objects. (The exception is this: When you design an API to call other code, the best API design is for a small speed boost.) But in your own internal code, try to implement it efficiently. )



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



4. The puzzle of performance



The previous version of the document gives a lot of misleading ideas, and here's some clarification:



On a device that does not have a JIT, it is more efficient to invoke the object passed by the method than the interface type (for example, passing the HashMap map is less expensive than invoking a method to pass the map map, although the map is hashmap in both cases). But this is not twice times the case, in fact, only 6%, and JIT makes the efficiency of both calls Briber.



On devices that do not have a JIT, accessing the cached field is about 20% faster than the direct Access field. In the case of JIT, field access and local access costs are the same. So it's not worth optimizing, unless you think he'll make your code easier to read (for Final,static, and static final variables as well).



5. Use static instead of virtual



If you do not need to access the fields of an object, set the method to static, and the call accelerates 15% to 20%. This is also a good practice, because you can use the method declaration to know that calling the method does not need to update the state of the object.



6. Avoid internal getters/setters



In the source language like C + +, it is common practice to use getters (I=getcount ()) Instead of direct access fields (I=mcount). This is a good habit in C + + because the compiler will inline these accesses, and if you need to constrain or debug access to these domains, you can add code at any time.



In Android, this is a bad idea. Virtual method invocation costs are much more expensive than direct access fields. There is a reason to use getters and setters in common interfaces according to the usual object-oriented language, but you should use direct access in a class that frequently accesses its fields.



Without JIT, direct field access is approximately 3 times times faster than calling an insignificant getter. When JIT is available (direct access to field costs and access to local variables is the same), 7 times times faster. This is true in the Froyo version, but will later improve the inline of the Getter method in the JIT.



7. Use the static final modifier for constants



Consider the first statement of the following class:



static int intval = 42;



static String Strval = "Hello, world!";



The compiler generates a class initialization method Clinit, which executes when the class is first used, and this method stores 42 in Intval and gets a reference to the class string constant strval. When these values are referenced later, they are accessed through the field lookup.



We improve implementation with final keyword:



static final int intval = 42;



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



Class no longer requires the Clinit method, because the constants go into the static field initializer in the Dex file. Refers to the Intval code, calls the cosmetic value 42 directly, and accesses the strval using a relatively inexpensive string constant (string constant) instruction instead of a field lookup. (This optimization is only for basic data types and string type constants, not for arbitrary reference types.) However, it is a good practice to declare constants as static final types as much as possible.



8. Using the improved for loop syntax



An improved for loop (sometimes referred to as a For-each loop) can be used to implement a collection class and an array of iterable interfaces. In the collection class, the iterator prompts the interface to access the Hasnext () and Next () methods, which are 3 times times faster (regardless of JIT) in ArrayList, but the improved for loop syntax and iterator are equally efficient in the other collection classes.



Here are some implementations of the iterative group: 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 the JIT cannot optimize the cost of getting the array length for successive iterations in this traversal.



One () is slightly faster, putting everything in a local variable, avoiding the lookup. But only the length of the array has contributed to improved performance.



Two () is the fastest run on a JIT-free device, and one () is the same for a device with a JIT. 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 the ArrayList iterations with a demanding performance.



9. In the private interior, consider using package access to override private access rights



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 a private internal class (Foo$inner) We define directly accesses a private method and a private variable in an external class. This is legal and the code will also print out the expected value is 27.



The problem is that virtual machines consider it illegal to access the private members of Foo from Foo$inner because they are two different classes, and although the Java language allows internal classes to access private members of external classes, the compiler generates several synthetic 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 inner class calls these static methods in any external class where you need to access the Mvalue field or the Dostuff method. This means that the code will attribute direct access to member variables to access via accessor methods. As mentioned earlier, how accessor access is slower than direct access, this example shows that some language conventions cause an invisible performance problem.



If you use this code in High-performance hotspot, you can access the package by declaring the fields and members that are accessed by the inner class, rather than the private. Unfortunately this means that these fields are accessed by other classes in the same package, so it is not appropriate to use them in the public API.



10. Rational use of floating point numbers



The usual experience is that in Android devices, floating-point numbers are twice times slower than int, in the absence of FPU, or JIT G1, and Nexus One with FPU and JIT (the absolute speed difference between two devices is about 10 times times that of arithmetic).



In terms of speed, there is no difference between float and double on modern hardware. More broadly, the double is about twice times larger. In a desktop machine with no storage space problems, double has precedence over float.



But even the integral type, some chips have hardware multiplication, but lack of division. In this case, integer division and modulo operations are implemented by software, considering when you design a hash table, or do a lot of arithmetic.


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.