Android code optimization tips and android code tips

Source: Internet
Author: User

Android code optimization tips and android code tips

This article mainly introduces some optimization tips for small details. When these tips are used in a comprehensive manner, they still play a role in improving the performance of the entire App, but they cannot greatly improve the performance. Choosing an appropriate algorithm and data structure should be your primary consideration. This is not covered in this article. You should use the tips in this article as the habit of writing code at ordinary times, which can improve the code efficiency.

Generally, efficient code must meet the following two rules:

  • Do not do redundant work
  • If possible, do not allocate memory.

One of the most difficult problems to solve when optimizing apps is to enable apps to run on various types of devices. Virtual machines of different versions have different running speeds on different processors. You can't even simply think that "device X is twice the speed of device Y", and then use this multiples to speculate on other devices. In particular, the running speed on the simulator has nothing to do with the speed on the actual device. Similarly, whether the device has JIT (instant compilation, Translator's note) also has a significant impact on the Running Speed: optimization Code in the case of JIT may not always be optimized without JIT.

To ensure that the App runs well on all devices, make sure that your code is optimized as much as possible on devices of different grades.

Avoid creating unnecessary objects

Creating an object is never costly. The generation-by-generation garbage collector in the thread allocation pool can make the allocation of temporary objects cheaper, but the allocation of memory is always more expensive than the non-allocation.

As you allocate more objects to the App, you may need to force GC (garbage collection, Translator's note) to reduce the stress for the user experience. The concurrent GC introduced in Android 2.3 will help you do this, but it should be avoided as much as possible after all.

Therefore, try to avoid creating unnecessary objects. Here are some examples to illustrate this problem:

  • If you need to return a String object and you know that it will eventually connect to a StringBuffer, modify your function signature and implementation method to avoid direct connection operations, create a temporary object for this operation.
  • When a String is extracted from the input dataset, the substring object of the original data is returned instead of creating a duplicate object. You will create a new String object, but it should share the internalchar[](The cost is that if you only use a small part of the original data, you only need to save this small part of the object in the memory)

A slightly radical approach is to break all multidimensional data into one-dimensional arrays:

  • A group of int data is much better than a group of Integer objects. We can know that the two groups of one-dimensional arrays are more efficient than a two-dimensional array. Similarly, this principle can be extended to other original data types.
  • If you need to implement an array to store (Foo, Bar) objects, remember that using Foo [] is much better than using Bar. (Except for some good API design, some compromises can be made as appropriate. However, in your own code, you should use it more easily after decomposition ).

Generally, avoid creating more temporary objects. Fewer objects mean fewer GC actions. GC has a direct impact on user experience.

Select Static instead of Virtual

If you do not need to access the value range of an object, please ensure that this method is static, so that the method call will be faster than 15%-20%. This is a good habit, because you can know from the method declaration that the call cannot change the state of this object.

Constant declared as Static Final

Consider the following declaration method:

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

The compiler will use a function to initialize the class and then execute it when the class is used for the first time. This function saves 42intVal, Also extracted from the constant table of the class filestrVal. UseintValOrstrValThey will be directly queried.

We can usefinalKeyword to optimize:

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

The above method is no longer required because the final declared constant enters the field initialization part of the static dex file. CallintValThe code will use 42 directly, callstrValThe code will also use a relatively cheap "String constant" command, rather than a look-up table.

Note: This optimization method is only valid for the original type and String type, rather than any reference type. However, if necessarystatic finalIs a good habit

Avoid internal Getters/Setters

Native languages such as C ++ usually use getters (I = getCount () instead of directly accessing the variable (I = mCount ). This is a good habit of writing C ++, and is usually used by other object-oriented languages, such as C # and Java, because the compiler usually performs inline access, besides, you need to restrict or debug variables. You can add code in getter/setter at any time.

However, on Android, this is a bad way of writing. Calling a virtual function is more expensive than directly accessing a variable. In object-oriented programming, it is reasonable to expose getter and setting to public interfaces. However, in the class, you should only use the domain for direct access.

Without JIT (Just In Time Compiler), direct access to variables is three times faster than the call to getter. With JIT, direct access to variables is seven times faster than getter access.

Note that if you use ProGuard, you can achieve the same effect, because ProGuard can be your inline accessors.

Use an enhanced For Loop

An enhanced For loop (also known as a for-each loop) can be used in collections and arrays that implement the Iterable interface. When collection is used, Iterator (Iterator, Translator's note) will be allocated for calling for-each.hasNext()Andnext()Method. When ArrayList is used, the handwritten counting for loop is three times faster (whether JIT exists or not), but for other collections, the improved for-each loop write method is the same as that of the iterator.

Compare the following three methods:

static class Foo {     int mSplat; }  Foo[] mArray = ...  public void zero() {     int sum = 0;     for (int i = 0; i < mArray.length; ++i) {         sum += mArray[i].mSplat;     } }  public void one() {     int sum = 0;     Foo[] localArray = mArray;     int len = localArray.length;      for (int i = 0; i < len; ++i) {         sum += localArray[i].mSplat;     } }  public void two() {     int sum = 0;     for (Foo a : mArray) {         sum += a.mSplat;     } } 
  • Zero () is the slowest because JIT cannot optimize it.
  • One () is faster.
  • Two () is the fastest without JIT, but after JIT, it is almost as fast as Method one. It uses the enhanced loop method for-each.

Therefore, use the for-each method whenever possible, but use the one () method for ArrayList ().

You can also refer to the 46th articles in Josh Bloch's objective Java book.

Use package-level access instead of private access of internal classes

Refer to the following code

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);     } } 

What is important here is that we define a private internal class (Foo$Inner), Which directly accesses the private methods and private member objects in the external class. This is legal, and the code will print "Value is 27" as expected ".

The problem is that the VMFooAndFoo$InnerIs different classes, will think inFoo$InnerDirect AccessFooThe private member of the class is invalid. Even if the Java language allows internal classes to access private members of external classes. To remove this difference, the compiler will generate some counterfeited functions:

/*package*/ static int Foo.access$100(Foo foo) {     return foo.mValue; } /*package*/ static void Foo.access$200(Foo foo, int value) {     foo.doStuff(value); } 

Every time an internal class needs to access mValue members in an external class or call the doStuff () function, it will call these static methods. This means that the above Code can be attributed to accessing member variables through the accessor function. As we said earlier, using accessor is slower than directly accessing the domain. Therefore, this is an example of performance degradation caused by specific language usage.

If you are using code like this in the performance hot zone (hotspot: high-frequency, repetitive code snippet), you can declare the domain and method to be accessed by the internal class as package-level access, instead of private access permissions. Unfortunately, this means that other classes in the same package can directly access these domains, so you cannot do this in public APIs.

Avoid using the float Type

In the Android system, the float data access speed is half of the int type, and the int type is preferred.

In terms of speed, float and double speed on modern hardware are the same. In terms of space, double is twice the float size. In the case that the space on the desktop is not a problem, you should use double.

Likewise, for integer types, some processors implement hardware multiplication several times, but there is no division. At this time, the division and remainder of integer types are implemented in the software, which should be taken into account when you use hash tables or a large number of blood transfusion operations.

Use library functions

In addition to common reasons that allow you to use built-in library functions, remember that system functions can sometimes replace third-party libraries and have assembly-level optimization, they are generally more efficient than the Code Compiled by Java with JIT. A typical example is:String.indexOf(), Dalvik replaces it for inline performance considerations. SimilarlySystem.arraycopy()The function is also replaced. This performance is tested on Nexus One, 9 times faster than a hand-written for loop and JIT.

See the first article in Josh Bloch's objective Java.

Use native functions with caution

Using native code development with Android NDK is not always more efficient than Java direct development. Java to native code is costly, and JIT cannot be optimized in this case. If you allocate resources in native code (such as memory on native stack, file descriptor, etc.), this will cause huge difficulties in collecting these resources. You also need to re-compile the code for various architectures (instead of relying on JIT ). You even need to compile multiple versions for devices with the same architecture: the version compiled for the G1 ARM architecture cannot fully use the advantages of the ARM architecture on Nexus One, and vice versa.

Native code is advantageous when you already have local code and want to port it to the Android platform, instead of optimizing the use of existing Android Java code.

If you want to use JNI, learn JNI Tips

See the first article in Josh Bloch's objective Java.

Misunderstandings about performance

On devices without JIT, using a specific data type is indeed more efficient than using abstract data types (for example, callingHashMap mapCompared with callingMap mapHigher efficiency ). The efficiency of mistaken transfer is doubled, but it is only about 6%. Besides, after JIT, there are not many differences between them.

On devices without JIT, it is about 20% faster to read the cache domain than to directly read the actual data. When JIT is available, domain reading is basically the same as local reading. So optimization is not worth it unless you think it makes your code easier to read (this applies to final, static, static final domains ).

About Measurement

Before optimization, you should decide that you have encountered performance problems. You should ensure that you can accurately measure the performance that appears, otherwise you will not know whether the optimization is really effective.

All the skills in this section require the support of Benchmark (Benchmark test. Benchmark can be found in code.google.com "dalvik" project

 

Benchmark is developed based on the Java version of Calipermicrobenchmarking (Benchmark micro-test, Translator's note) framework. Microbenchmarking is difficult to make accurate, so Caliper helped you complete this part of the work, and even helped you test what you did not expect to measure (because the VM helped you manage code optimization, it is hard for you to know how much the optimization works ). We strongly recommend using Caliper for your benchmark microtest.

We can also use Traceview for measurement, but the measurement data is not optimized by JIT, so the actual effect should be slightly better than the measurement data.

You can refer to the following two articles to learn how to measure and debug data:

  • Profiling with Traceview and dmtracedump
  • Analysing Display and Performance with Systrace
  • Q: one-click call to programmer Q & A artifacts, one-to-one service, developer programming required official website: www.wenaaa.com

    QQ Group 290551701 has gathered many Internet elites, Technical Directors, architects, and project managers! Open-source technology research, welcome to the industry, Daniel and beginners interested in IT industry personnel!

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.