Optimization points neglected in Android Performance Optimization

Source: Internet
Author: User

Optimization points neglected in Android Performance Optimization

The knowledge point of performance optimization is too broad, and the blogger himself has been very concerned about this learning. For performance optimization, it involves a lot of aspects, such: i/O optimization, network operation optimization, memory optimization, data structure optimization, code level optimization, UI rendering optimization, CPU resource usage optimization, exception handling optimization, etc. and so on...

This article describes some optimizations in Android development based on the understanding of bloggers.

ArrayList and Vector

Both ArrayList and Vector are internally implemented by arrays. The only difference between them is their support for multithreading. ArrayList is thread-insecure, while Vector synchronizes most methods internally, it is thread-safe. Since it is thread-safe, the performance is definitely not as good as that of ArrayList (of course the idea is correct), but it depends on which aspect, the efficiency of ArrayList operations, such as add, get, and remove, must be higher than that of Vector operations. In terms of memory, the Vector performance is better than that of ArrayList, which is ultimately caused by the expansion policy of ArrayList, analyze later.

Implement the set of RandomAccess interfaces and use fori Traversal

First, let's talk about the traversal methods of List sets. There are three methods: foreach, iterator, and fori.
In development, the first choice must be foreach. Because of its high efficiency, this is correct, but it needs to be divided into occasions.
The following is an ArrayList set that uses these three methods to test traversal of million pieces of data:

Long start = System. currentTimeMillis (); for (int I = 0; I <size; I ++) {data. get (I);} long end = System. currentTimeMillis (); Log. v (zxy, fori cost: + (end-start); start = System. currentTimeMillis (); for (Integer integer: data) {} end = System. currentTimeMillis (); Log. v (zxy, foreach cost: + (end-start); Iterator
  
   
Iterator = data. iterator (); start = System. currentTimeMillis (); while (iterator. hasNext () {iterator. next ();} end = System. currentTimeMillis (); Log. v (zxy, iterator cost: + (end-start ));
  
11-19 09:11:44. 276 1418-1418 /? V/zxy: fori cost: 3011-19 09:11:44. 380 1418-1418 /? V/zxy: foreach cost: 10511-19 09:11:44. 476 1418-1418 /? V/zxy: iterator cost: 95

In general, the highly efficient foreach seems unsatisfactory in traversal, while the fori efficiency is the best, because the internal implementation of ArrayList and Vector sets is implemented by arrays, therefore, the random access speed is very fast. For the List with random access, JDK implements the RandomAccess interface for them, indicating that fast random access is supported.
When traversing the collections list set with 1 million pieces of data:

11-19 09:33:23. 984 1737-1737 /? V/zxy: fori cost: 35111-19 09:33:23. 988 1737-1737 /? V/zxy: foreach cost: 211-19 09:33:23. 992 1737-1737 /? V/zxy: iterator cost: 4

Foreach performs the best, so the fori performance is the best for the array or the List that implements the RandomAccess interface, and the foreach or iterator performance is the best for the collection times that are implemented by the linked List, because foreach is implemented through iterator.
We can determine which method is used to traverse the List as follows:

        if (list instanceof RandomAccess)        {            for (int i = 0; i < list.size(); i++) {}        } else {            Iterator
   iterator = list.iterator();            while (iterator.hasNext()) {                iterator.next();            }        }
Specify the initial size when constructing an ArrayList with a predicted capacity

The internal expansion policy of ArrayList is that when the number of elements it stores exceeds its existing size, it will resize at 1.5 times, that is, if the current ArrayList capacity is 10000, when it needs to store another element, that is, 10,001st elements, it will perform a resizing due to insufficient capacity, the size of the ArrayList after expansion is changed to 15000, and the space of 5000 elements is increased when one element is added, which is a waste of memory resources, in addition, the expansion will also result in a memory replication of the entire array, and the default size of the ArrayList set is 10. Therefore, setting the ArrayList capacity properly can avoid the expansion of the set. ArrayList internal expansion and array copy code:

            Object[] newArray = new Object[s +                    (s < (MIN_CAPACITY_INCREMENT / 2) ?                     MIN_CAPACITY_INCREMENT : s >> 1)];            System.arraycopy(a, 0, newArray, 0, s);            array = a = newArray;

The internal expansion policy of Vector is on-demand expansion, each time + 1:

        if (capacityIncrement <= 0) {            if ((adding = elementData.length) == 0) {                adding = 1;            }        } else {            adding = capacityIncrement;        }        E[] newData = newElementArray(elementData.length + adding);

Similarly, many Map sets also have their own resizing policies. For example, the new capacity of HashMap is equal to the original capacity * 2 each time it is resized. In StringBuffer and StringBuilder, which are commonly used for String concatenation, there is actually a resizing strategy. By default, the expansion is 1.5 times the original size.

Therefore, if you know the data size in advance for these APIs to be resized, you can set them in advance to avoid space waste caused by expansion and avoid calling System internally. arraycopy () performs mass data replication.

If the program needs to perform random access to the List through index subscript, The ArrayList and Vector should be given priority, and the sequence List should not be used as a last resort.

Although ArrayList is less efficient than Vector in memory, it is highly efficient in data operations, especially on Android and other mobile devices, in terms of thread security, Vector is used.

If a method does not need to use members of this object, set this method to static.

Static call of this method is 15% ~ Faster than object call of this method ~ 20%, because it can be seen from the method signature that the method call will not affect the status of the object

Clever Use of final keywords

The final keyword is usually used to define constants and Methods. Most people often understand final in non-variability, and final also plays a major role in performance optimization.
For example: static int AGE = 10; when 10 is referenced later, there will be a field search process. For int type, that is, the integer constant pool in the Search Method Area, for final constants, this process is omitted, for example: static final int AGE = 10; where AGE is used, it will be replaced by 10 directly.

However, the above optimization technique is only valid for the basic type and String type, and is invalid for other reference types, but it is still a good habit to add static final when declaring constants.

There is also a powerful role for the final keyword, that is, to define final for methods that are frequently used and have been identified as the final state. What are the advantages of this?

Let's talk about the execution process of methods in java first. When a method is called, The method first enters the stack. After the execution is complete, the method goes out of the stack and resources are released, in this process, the memory address is actually transferred. When the method is executed into the stack, the execution address of the program is actually transferred to the memory address stored in this method, before this operation, the memory address stored in the original program must be executed. After the method is executed out of the stack, the program continues to be executed at the saved address, is the process of calling a method.

Therefore, the call process of a method actually requires space and time, and the optimization of frequent calls to the same method is actually using the inline method.

When it comes to inline functions, inline functions are actually optimized during the compilation period. The compiler will directly replace the inline functions with the entire function body in the called place, this saves the amount of time resources that function calls consume, but increases the amount of target code. Therefore, the inline optimization strategy is actually a space-for-time strategy, for mobile terminals, the clever use of inline functions is actually very beneficial.

If a function becomes an inline function, it is defined as final. In this way, the compiler automatically performs inline Optimization on the final function during program compilation, when calling this function, expand the function body for use.

To sum up, it is not the more inline functions, the better. On the one hand, it does improve the running efficiency of our programs, and on the other hand, it will be self-defeating if too many inline functions are used, it is possible to increase the method body of a method. For methods with a large method body, the time for Inline expansion may exceed the time for method calling, therefore, this not only does not provide performance, but also reduces the expected performance.

In summary, we can use final to modify methods that are frequently used and have been identified as the final state, and provide program performance.

Give priority to the Code provided by the system rather than writing it by yourself.

The System has many built-in very convenient APIs for us to use, such as System, Arrays, Collections, String, and many other built-in method APIs, which is much more convenient than writing by ourselves, in addition, for Android, many APIs use the underlying C/C ++ implementation, so the efficiency is faster than we write. Similarly, for system APIs, DVM often uses inline methods to improve efficiency.

Usage with caution

To use exceptions with caution, you do not need to use exceptions. Instead, you can use throwing exceptions to execute certain operations in the program. For example, some may use the method of throwing exceptions to interrupt some operations. When an exception is thrown, fillInStackTrace () is executed. The function of this method is to re-adjust the stack, which makes it unnecessary to avoid exceptions.

 

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.