Android developer Guide (17) -- Designing For Performance

Source: Internet
Author: User
Tags integer division

 

Preface

This chapter is about the developer Guide/Best Practices/Designing For Objective C, which is translated as "performance optimization" in Android3.1 r1 ", welcome to his blog: "http://admires.iteye.com/", thank you again "qiongju@gmail.com "! We look forward to your participation in translation of Android related information, contact me over140@gmail.com.

 

Statement

You are welcome to repost, but please keep the original source of the article :)

Blog Garden: http://www.cnblogs.com/

Android Chinese translation group: http://goo.gl/6vJQl

 

Designing for Performance

Qiongju@gmail.com

Link: http://admires.iteye.com/

Version: Android 3.1 r1

 

Original

Http://developer.android.com/guide/practices/design/performance.html

 

Performance Optimization

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.

 

Introduction

There are two basic principles for writing efficient code:

* Unnecessary work.

* Try to avoid memory allocation.

 

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 ). Development Investment time is limited, so wise time planning is very important.

(For more analysis and notes, see the summary .)

This document also ensures that you make the best choice on algorithms and data structures while considering the potential impact of API selection. The use of appropriate data structures and algorithms is more valuable than any suggestions here. The impact of API versions is preferred to help you find better implementations. (This is more important in the class library code than in the application code)

(If you need such a suggestion, see Josh Bloch'sValid Java, Item 47 .)

When optimizing the Android program, you may encounter a tricky problem: ensure that your program can run on different hardware platforms. The Virtual Machine version is the same as the processor version, so the running speed is quite different. However, this is not simple. A is faster or slower than B and can be arranged between devices. In particular, the simulator can only evaluate a small part of the device. There is also a huge difference between devices with or without JIT. Good code on JIT devices sometimes does not work well on devices without JIT.

If you want to know the specific performance of a program on the device, you must test it.

 

Avoid creating unnecessary objects

Object creation will never be free. Each thread's generational GC allocates an address pool to the zero-time object to reduce the allocation overhead. However, it usually costs a lot to do not allocate the memory proportion.

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

Therefore, unnecessary object creation should be avoided. The following are examples:

* If a method returns a String, and its return value is often appended to a StringBuffer, the declaration and implementation are changed so that the function can be directly appended to it, instead of creating a temporary zero-time variable.

* 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, although you create a new object, they share the char array of the data. (The result is that even if only a part of the original input is used, you need to ensure that it is always in the memory .)

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

* Arrays of the Int type usually have the remainder Integer type. By extension, two parallel int arrays are more efficient than an (int, int) object array. This is common for any other combination of basic data types.

* If you need to implement a container to store the tuples (Foo, Bar), two parallel arrays Foo [] and Bar [] will be better than an array of (Foo, Bar) objects. (Exception: when you design an API to call other code, the well-applied API design can be used in exchange for a small increase in speed. But try to implement it efficiently in your internal code .)

In general, try to avoid creating objects when the short time is zero. A small number of objects mean low-frequency garbage collection. This has a direct impact on the user experience.

 

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 efficient to use the specific type of the object to call a method than to use the interface type (for example, it is less costly to pass a HashMap map Map than map to call a method, although both maps are HashMap ). but this is not a two-fold slow situation. In fact, they only differ by 6%, while the two calls are equally efficient when there is JIT.

On devices without JIT, the cached field access is about 20% faster than direct access. In the case of JIT, field access costs are equivalent to local access, so it is not worth optimizing unless you think it will make your code easier to read (for final, static, and static final variables)

 

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 see from the method declaration that calling this method does not need to update the state of this object.

 

Avoid internalGetters/Setters

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

In Android, this is not a good practice. Virtual method calls are much more expensive than direct field access. Generally, based on the object-oriented language practice, it makes sense to use Getters and Setters in public interfaces, but direct access should be used in classes where a field is frequently accessed.

When there is no JIT, direct field access is about three times faster than getter access. With JIT (direct access to field overhead is equivalent to local variable access), it is 7 times faster. This is true in Froyo, but later versions may improve the inline of the Getter method in JIT.

 

Constant usageStatic FinalModifier

Consider the following statement:

  

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

We improved the implementation by using the final Keyword:

  

The <clinit> method is no longer required for the class, because constants enter the dex file through the static field initiator. Referencing the intVal code will directly call the integer value 42. Accessing strVal will also use a "String constant" with a relatively low overhead (original article: "sring constant ") command substitution 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 as much as possible.

 

Improved usageForLoop syntax

An improved for loop (sometimes called a "for-each" loop) can be used in collection classes and arrays that implement the iterable interface. In the collection class, the iterator asks the interface to call the hasNext () and next () methods. In ArrayList, handwritten counting loop iterations are 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:

  

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

One ()Faster. Put everything into local variables to avoid searching. However, only declaring the length of an array can improve performance.

Two ()It 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.

(SeeValid JavaItem 46 .)

 

In private, you should consider replacing the private access permission with the package access permission.

Consider the following definition:

  

The key to note is that we define a private internal class (Foo $ Inner) to directly access a private method and private variable in the external class. This is legal and the code will also 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.

  

The internal class calls these static methods wherever the external class needs to access the mValue field or call the doStuff method. This means that the Code directly accesses member variables as accessed through the accessor method. I have mentioned how slow accessors are compared with direct access. This example shows that some language appointments 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. However, this also means that these fields will be accessed by other classes in the same package, so they are not suitable for public APIs.

 

Reasonable Use of Floating Point Numbers

Generally, in Android devices, floating point numbers are twice slower than integer types, this is true in the Nexus One with FPU and JIT compared to G1 without FPU (the absolute speed difference between the two device arithmetic operations is about 10 times)

In terms of speed, there is no difference between float and double in modern hardware. More broadly speaking, double is two times larger. On a desktop, because there is no space problem, double has a higher priority than float.

However, even if it is an integer, some chips have hardware multiplication, but there is no division. In this case, integer division and modulo calculation are implemented by software, just like when you design a Hash table or do a lot of arithmetic operations.

 

Understand and use the class library

Select the code in the Library instead of self-rewriting, except for the common reasons, considering that the system will use the Assembly Code call to replace the library method when the system is idle, this may be better than the best equivalent Java code generated in JIT. A typical example is String. indexOf. Dalvik is replaced by internal inline. Similarly, the System. arraycopy method has a self-coding cycle of 9 times faster on the JIT Nexus One.

(SeeValid JavaItem 47 .)

 

Rational use of local methods

The local method is not necessarily more efficient than Java. At the very least, there is consumption in the transitional association between Java and native, and JIT cannot optimize it. When you allocate local resources (memory on the local stack, file specifiers, etc.), it is often difficult to recycle these resources in real time. At the same time, you also need to compile your code in various structures (rather than relying on JIT ). Different versions may even need to be compiled for the same architecture: the local code compiled for the GI of the ARM processor cannot fully utilize the ARM on Nexus One, the local code compiled for the ARM on Nexus One cannot be run on the ARM on G1.

When you want to deploy a program to an Android platform with a local code library, the local code is particularly useful, not to speed up Java applications.

(SeeValid JavaItem 54 .)

 

Conclusion

Finally, we usually consider the following: first determine the problem and then optimize it. And you know the performance of the current system. Otherwise, the improvement you have attempted cannot be measured.

Each claim in this document is supported by a standard benchmark. You can find the benchmark code in the "dalvik" project of code.google.com.

This standard benchmark is built on the Caliper Java standard micro Benchmark Testing Framework. The standard micro-benchmark test is difficult to find the correct path, so Caliper helped you complete the difficult part of the test. And when you notice the test results in some situations and think that way (virtual machines are always optimizing your code ). We strongly recommend that you use Caliper to run your own standard microbenchmark.

At the same time, you will also find that Traceview is useful for analysis, but you must understand that it currently does not support JIT, which may lead to code running times out that can win the JIT. It is particularly important to make changes based on the Taceview data to ensure that the code runs faster without Traceview.

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.