Performance Optimization Tips

Source: Internet
Author: User
Tags benchmark integer division

Https://developer.android.com/training/articles/perf-tips.html

这篇文章主要讲述了一些小优化,但是如果把这些小优化都结合起来的话则会提高一个app的整体性能。不过这也不代表对于性能它们会有质的改变。首当其冲是选择正确的算法和数据结构,不过它不在本篇文章的讨论范围内。你应该将本篇文章讨论的小技巧融入到编码习惯中以提示通用编码效率。

There are two basic principles for writing efficient code:

    • Don't do too much of what you don't need to do.
    • Do not use the memory you can not

The tricky problem with fine-tuning an app is that the app is bound to run on a variety of hardware. Different versions of VMs run on different processes at different speeds. It is not a generic situation, you can simply say "device X for what reason is faster/slower than device Y", and can extend the results from one device to another device. There is also a huge difference for devices that have no JIT. The best way to encode a JIT-equipped device is usually not the best for a device that doesn't have a JIT.

To ensure that your app performs well on a wide variety of devices, you need to make sure that your code is efficient for each version and actively optimizes performance

Avoid creating useless objects

There is always a price to create objects. A generation GC with thread allocation pools created for temporary objects reduces the cost, but allocating memory is always more expensive than allocating memory

When a lot of objects are allocated in the app, the periodic GC is triggered, and the user experience appears in Dayton. Asynchronous GC has been introduced in Android2.3, but unnecessary work should be avoided

Therefore, you should avoid creating unwanted objects, and some of the following examples may help:

    • If you need a method that returns a string, the result should be stringbuffer anyway, changing the definition and implementation of the function so that the function can return directly instead of creating a temporary object
    • When extracting a string from the raw data, you should return the substring of the original data instead of creating a copy. You will create a new string object, but it shares char[with the original data] (the tradeoff is if you only need a small fraction of the original data, if you do, you will always hold it in memory)

Some of the more radical approaches are to cut a multidimensional array into a single one-dimensional array:

    • An array of int is better than an array of integers, and two one-dimensional int arrays are more efficient than (int,int) two-dimensional arrays. For other primitive data types this principle also applies
    • If you need to implement a storage (Foo,bar) container, remember that foo[] and bar[] arrays are better than (Foo,bar). (There are exceptions, of course, when you're designing an API for other code, which makes some speed compromises better for better API design). But in your own code, you should try to use more efficient code.

In general, do everything possible to avoid creating temporary objects, fewer object creation means less frequent GC, and GC directly impacts the user experience

Use static better than virtual

If you do not need to access the fields of an object, the call is 15%~20% by using a static method. This is also a good practice because you can differentiate from the method signature and call the method without changing the state of the object

Constants are modified with static final

Consider the following types of declarations at the beginning of a class

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

The compiler generates a class initialization method, called, which executes when the class is first used. This method stores a value of 42 in Intval and extracts a reference for Strval in the class file string constant table. When called after these values, they can be referenced directly by the property.

We can use the ' final ' keyword to improve the code

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

This class will no longer need a method because these constants have been directly written to the static property initialization of the Dex file. Intval can use 42 directly, access Strval can also use the less expensive ' string constant ' instead of property calls

Note: This optimization applies only to the original data type and to the string variable, not to any type. Of course, it's a good practice to use static final in any possible situation.

Avoid internal use getters/setters

Some native languages, such as C + +, typically use Getter (I=getcount ()) Instead of direct access to variables (i = mCount). Is a good habit for C + + and is often used in other object-oriented languages such as C # and Java. Because the compiler can embed access and if you need to restrict or debug code access, you can add it at any time

However, for Android this is a bad habit, the call of the virtual method is more expensive than the Instance property query, and it is well justified to follow the practice of object-oriented programming in the common interface place using the Get Set method. But inside a class you should still have direct access to the properties

If there is no JIT, accessing the property directly is more than 3x faster than calling the Get method. If there is a JIT (the cost of directly accessing the property is the same as accessing local), accessing the property directly is more than 7x faster than calling the Get method

If you use Proguard, you can have both worlds because Proguard has built-in accessors for you

Using the enhanced loop syntax

An enhanced loop, such as For-each loop, can be used to implement the Iterable collection and array. The collection needs to implement the interface Hasnext () and Next () methods. The ArrayList is 3x faster than the handwritten loop (there is no JIT in stock), but for other aggregate-enhanced loops it is exactly the same as the use of the display iterator

Here are some scenarios for traversing arrays:

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

Zer () is the least efficient because the JIT cannot optimize the cost of getting an array size per loop in the entire cycle

One () is relatively fast, it turns everything into a local variable, avoids lookups, and only the array length provides performance benefits.

Both () is the fastest for devices that do not have a JIT, and is the same as one () for devices with JIT. It uses the enhanced loop syntax introduced after Java 1.5

Can view Josh Bloch ' s effective Java, item 46

Using the package instead of using private inline classes

Consider the following definitions:

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 most important thing here is that we define a private inner class (Foo$inner) that accesses a private method and a private instance property directly in the external class. This is legal, this code prints the ' Value is 27 ' on schedule

The problem is that the virtual machine thinks that through Foo I NNeR StraightConnectVisitAskF ooof thePrivatehave aintomemberis aNon-Methodof the,becauseto beF ooand theF oo Inner are different classes, although the Java language allows an inner class to access private members of an external class. To eliminate this problem, the compiler generates a pair of synthetic methods

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

This inner class calls these static methods at all places that require access to the external class Mvalue property and calls the Dostuff () method, which means that the code mentioned above can actually be used to access the member variable if it really boils down to a situation. How the accessors mentioned earlier are slower than the direct access property, which is an invisible performance impact due to language habits

If you use such code somewhere in a performance hotspot, you can avoid declaring variables and methods overhead by accessing internal classes that have package access, rather than private access permissions. Unfortunately this means that attributes can be accessed directly from other classes under the same package, so you should avoid doing so in the public API

Avoid using floating-point types

Based on experience, floating point data on Android devices is 2x slower than integer type

In terms of speed, there is no difference between a float and a double on more modern hardware, with a double occupying 2x or more on a space footprint. Just like a desktop, if space is not a problem, you should use double instead of float

Similarly, even for integer types, some processors have hardware multiplication but no division. In this case, the integer division and modulo operations are implemented by software-if you want to design a hash table or do a lot of math, you need to consider these things.

Understand and will use the following libraries

In addition to the usual reasons to use the library instead of your own implementation, it is necessary to remember that the system is free to use manual coding instead of library method calls, which may be better than the JIT can provide the best Java code. A typical example is that String.IndexOf () and other related Apis,dalvik will be replaced with inline intrinsic functions, the same way that the System.arraycopy () method is faster than a loop with a JIT Nexus one manual write 9x

Can view Josh Bloch ' s effective Java, item 47

Cautious use of local methods

Writing native code using the Android NDK is not necessarily more efficient than writing in Java. On the one hand, there is a cost to the conversion of java-native, and the JIT cannot bypass the boundary to do the optimization. If you are applying for local resources (local heap memory, file descriptors, or anything else), it is very difficult to reclaim these resources. And you have to compile different versions of the same system's CPUs: compiling native code for G1 arm processors may not take full advantage of Nexus One's arm, and vice versa

Local code is used to speed up your existing local code library to Android instead of Android app

If you need to use local code, you can read the JNI Tips

can view Josh Bloch ' s effective Java, item 54

Performance Myths

Without a JIT device, it is more efficient to invoke a method with an exact type than to invoke the method with an interface (for example, using HashMap map is less expensive than a map map call method, although both of these maps are HASHMAP), it is not actually half as slow, but 6% slower. In addition, there are JIT equipment, difficult to distinguish the pros and cons

Without a JIT device, access to the cache field is 20% faster than repeated field access. With a JIT device, the domain variable access cost is the same as the local variable access cost, so there is no need to optimize unless you feel it can make your code easier to read (and Final,static,static final is more true)

Frequently measured

Before you start optimization, make sure you have some problems to solve. Make sure you can measure your existing performance accurately, otherwise you won't be able to measure the benefits of the alternatives you're trying to

Each statement in this article has benchmarks, and the source code for the benchmark test can refer to code.google.com "Dalvik" project.

These benchmarks are based on the caliper micro-benchmark Java framework. The micro-benchmark is hard to get right, so caliper for you to do more than it does in a way that even detects something you want to measure but no measurement (because the VM optimizes all your code). We strongly recommend that you use Caliper to run your own micro-benchmark

You may find that TraceView is useful for analysis, but you need to know that it is currently not compatible with the JIT, which can lead to some time when the JIT will perform better. It is particularly important to ensure that the code optimized with TraceView is indeed faster than the code that does not use TraceView.

For more analysis and debugging apps, refer to:

Profiling with Traceview and Dmtracedump

Analyzing UI performance with Systrace

Performance Optimization Tips

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.