Android memory and performance optimization Summary
1. Instant Compilation (Just-in-time Compilation, JIT), also known as Dynamic Translation (Dynamic Translation), is a way to translate bytecode into machine code at runtime, this improves the performance of bytecode compiling languages. The two runtime theories at the early stage of real-time compilation are bytecode compilation and dynamic compilation. Android uses the Dalvik virtual machine as an interpreter. The new version (Android2.2 +) will be implemented by the JIT compiler. Performance tests show that new versions in multiple tests are about six times higher than earlier versions.
2,
Just like there is no free lunch in the world, and there are no free objects in the world. Although gc creates a temporary object pool for each thread, it can reduce the cost of object creation, but the cost of memory allocation is always higher than that of memory allocation. If you allocate the object memory in the user interface loop, it will lead to periodic garbage collection, and the user will feel that the interface is as choppy. Therefore, unless necessary, try to avoid the instance of the object as much as possible. The following example will help you understand this principle: When you extract a string from user input data, try to use the substring function to obtain a substring of the original data, instead of creating another copy for the substring. In this way, you have a new String object, which shares a char array with the original data. If you have a function that returns a String object, and you know exactly that the String will be appended to a StringBuffer, change the parameter and implementation method of this function, directly append the result to StringBuffer, instead of creating a short-lived temporary object.
A more extreme example is to divide a multi-dimensional array into multiple one-dimensional arrays:
The int array is better than the Integer array, which also summarizes the basic fact that two parallel int arrays provide much better performance than the array of (int, int) objects. Similarly, this is intended for a combination of all basic types. If you want to use a container to store (Foo, Bar) tuples, try to use two separate Foo [] arrays and Bar [] arrays, which must be equal to (Foo, Bar) array efficiency is higher. (There is also an exception, that is, when you create an API to allow others to call it. At this time, you should pay attention to the design of the API interface and sacrifice a little speed. Of course, you still need to improve the code efficiency as much as possible within the API)
In general, it is to avoid creating short-lived temporary objects. Reduce the creation of objects to reduce the garbage collection, and thus reduce the impact on user experience.
3. Static methods instead of Virtual Methods
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.
4. Avoid internal Getters/Setters
5. cache members locally
Accessing member variables is much slower than accessing local variables. The following code:
For (int I = 0; I
It is best to change it to this:
int count = this.mCount;Item[] items = this.mItems;for(int i =0; i < count; i++) { dumpItems(items);}
Another similar principle is: Never call any method in the second condition of. As shown in the following method, the getCount () method is called every time a loop is executed, which is much more overhead than saving the result in an int.
Similarly, if you want to access a variable multiple times, you 'd better create a local variable for it first, for example:
Here, the member variable mScrollBar is accessed four times. If it is cached locally, the four member variable accesses will become four more efficient stack variable accesses.
In addition, the efficiency of method parameters is the same as that of local variables.
6. Use the static final modifier for Constants
Let's take a look at the Declaration of the two paragraphs before the class:
static int intVal = 42;static String strVal = "Hello, world!"
It will generate a method of initialization class called clinit. This method will be executed when the class is used for the first time. The method will assign 42 to intVal, and then assign a reference pointing to a common table in the class to strVal. When these values are used in the future, they will be found in the member variable table. Let's make some improvements and use the keyword "final:
Static final int intVal = 42; static final String strVal = "Hello, world! "; Currently, the clinit method is no longer required for classes, because constants are directly saved to class files during member variable initialization. The code that uses intVal is directly replaced with 42, and strVal points to a String constant instead of a member variable.
Declaring a method or class as final will not improve the performance, but will help the compiler optimize the code. For example, if the compiler knows that a getter method will not be overloaded, the compiler will use inline calls to it.
You can also declare the local variable as final, which will not improve the performance. Using "final" can only make the local variables look clearer (but sometimes this is required, for example, when using anonymous internal classes ).
7,
Use improved For loop syntax
Improved for loop (sometimes called 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 (whether JIT exists or not), but in other collection classes, the improved for loop method and iterator have the same efficiency. The following shows how to access arrays in a set:
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; }}}
In zero (), each loop accesses two static member variables to obtain the length of an array.
In one (), all member variables are stored locally.
Two () uses the foreach syntax introduced in java1.5. The compiler saves the array reference and length to the local variable, which is very good for accessing array elements. However, the compiler will also generate an additional storage operation on local variables (access to variable a) in each loop, which will be 4 bytes more than one, the speed is a little slower.
8,
Avoid floating point number
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 the G1 without FPU and JIT (the absolute speed difference between arithmetic operations between the two devices is about 10 times) in terms of speed, in modern hardware, float and double are no different. 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 through software, just like when you design a Hash table or do a lot of arithmetic operations, for example, a/2 can be changed to a * 0.5.
9,
Reduce Unnecessary global variables
Avoid using static member variables to reference instances that consume too much resources, such as Context. Android provides a sound message transmission mechanism (Intent) and task model (Handler). It can prevent unnecessary global variables through transmission or event.
10,
Four Java reference methods
In JDK 1.2, object references are classified into four levels, so that the program can control the object lifecycle more flexibly. The four levels are from high to low: strong reference, soft reference, weak reference, and virtual reference.
I. StrongReference)
Strong references are the most common references. If an object has a strong reference, the garbage collector will never recycle it. When the memory space is insufficient, the Java Virtual Machine would rather throw an OutOfMemoryError to terminate the program abnormally, and does not recycle strongly referenced objects at will to solve the problem of insufficient memory.
Ii. SoftReference)
If an object only has soft references, the memory space is sufficient and the garbage collector will not recycle it. If the memory space is insufficient, the memory of these objects will be recycled. The object can be used by programs as long as the garbage collector does not recycle it. Soft references can be used to implement memory-sensitive high-speed cache.
Iii. WeakReference)
When the Garbage Collector thread scans the memory area under its jurisdiction, its memory will be recycled no matter whether the current memory space is sufficient or not. However, since the garbage collector is a thread with a low priority, it may not soon find objects with weak references.
Iv. PhantomReference)
As the name suggests, it is just a virtual setting. Unlike other references, virtual references do not determine the object lifecycle. If an object only holds a virtual reference, it is the same as no reference and may be recycled by the garbage collector at any time. Understanding and mastering the reference methods in these 4 fields, selecting the appropriate object application method is helpful for memory recovery.
See http://blog.csdn.net/feng88724/article/details/6590064 for details
Cache is often used in Android:
A. Thread Pool
B. Android image cache, Android image Sdcard cache, and data prefetch Cache
C. Message Cache
Use handler. obtainMessage to reuse the previous message, as shown below:
1 |
Handler. sendMessage (handler. obtainMessage (0, object )); |
D. ListView Cache
E. Network Cache
The database caches http response and determines the Cache expiration time based on the Cache-Control domain in the http header information.
F. file IO Cache
The input stream with a cache policy is used. BufferedInputStream replaces InputStream, BufferedReader replaces Reader, and BufferedReader replaces BufferedInputStream. This applies to files and network I/O.
G. layout Cache
H. Other data caches that require frequent access or one access consume a large amount of data
(2) Data Storage Optimization
Including selection of data types and data structures.
A. Data Type Selection
String concatenation replaces String with StringBuilder, and replaces StringBuffer with StringBuilder without concurrency. If you have a general understanding of the length of a string, such as about 100 characters, you can directly specify the initial size in new StringBuilder (128) to reduce the allocation when the space is insufficient.
Processing of 64-bit data such as long double is slower than processing of 32-bit data such as int.
SoftReference and WeakReference are more conducive to system garbage collection than normal applications.
The final type is stored in the constant area for higher Read efficiency.
LocalBroadcastManager replaces normal BroadcastReceiver with higher efficiency and security.
B. Data Structure Selection
Common Data Structure options include:
In the selection of ArrayList and sort list, ArrayList takes a faster value based on the index. The sort list occupies more memory, the random insertion and deletion speed, and the expansion efficiency is higher. ArrayList is generally recommended.
Select ArrayList, HashMap, LinkedHashMap, and HashSet. The query speed of hash data structures is better. ArrayList stores ordered elements. HashMap is the key-value pair data structure. LinkedHashMap can remember the hashMap added to the order, repeated elements are not allowed in HashSet.
Select HashMap and WeakHashMap. The elements in WeakHashMap can be automatically recycled by the system garbage collector when appropriate, so it is suitable for use in memory-intensive scenarios.
Collections. The choice of synchronizedMap and ConcurrentHashMap, ConcurrentHashMap is a subdivision lock, the lock granularity is smaller, and the concurrency performance is better. Collections. synchronizedMap is the object lock. It is more convenient to add functions to implement lock control.
Android also provides some data types with better performance, such as SparseArray, SparseBooleanArray, SparseIntArray, and Pair.
The data structure of the Sparse series is a special processing case where the key is int. It adopts binary search and simple array storage, and does not require the overhead of generic conversion, which is superior to that of Map. But I don't quite understand why the default capacity is 10. Have you done data statistics? Or do you still have to consider these things when writing 16, we recommend that you set the initial value based on your possible capacity.
(3). Algorithm Optimization
This topic is relatively large and requires detailed analysis of specific issues. Do not use algorithms with O (n * n) time complexity or higher, and change the available space for time when necessary.
Consider hash and binary for query, and do not use recursion as much as possible. You can learn from structured algorithms or Microsoft or Google interview questions.
(4). JNI
Android applications are mostly developed in Java. the JIT compiler of Dalvik is required to run the code at the cost of Java bytecode conversion. The local code can be directly executed by the Device Manager, saving the intermediate steps, therefore, the execution speed is faster. However, it requires overhead to switch from the Java space to the local space, and the JIT compiler can also generate optimized local code. Therefore, poor local code may not necessarily have better performance.
This optimization point will be described in a separate blog later.
(5). Logical Optimization
This is different from the algorithm, mainly to clarify the program logic and reduce unnecessary operations.
(6). Demand Optimization
This will not be said. For the performance problems that may arise from sb requirements, we can only say that as a qualified programmer, we should not only be the performer, but also learn to say NO. However, you cannot use this interface to fool the product manager.
2. asynchronous, using multithreading to improve TPS
Take full advantage of multi-core Cpu and use threads to handle intensive computing, IO, and network operations.
For more information about multithreading, see:
In Android applications, due to system ANR restrictions, the master thread timeout operation may be put into another working thread. Handler can be used to interact with the main thread in the work thread.
3. Advance or delay operations to increase TPS by mistake
(1) Delayed operations
Delay is not applicable to time-consuming operations in response-sensitive functions such as Activity, Service, and BroadcastReceiver lifecycles.
In Java, you can use ScheduledExecutorService for delayed operations. Timer. schedule is not recommended;
In addition to ScheduledExecutorService, Android also supports some delay operations, such
Handler. postDelayed, handler. postAtTime, handler. sendMessageDelayed, View. postDelayed, and AlarmManager timing.
(2) advance operations
For the time-consuming operations that are called for the first time, they can be put into initialization in advance. For example, obtain the wallpaper wallpaperManager. getDrawable ();
4. Network Optimization
The following are some principles that clients and servers need to comply with in network optimization:
A. The image must be cached. It is best to make image adaptation based on the model.
B. httptimeout must be added for all http requests.
C. api interface data is returned in json format, instead of xml or html
D. Check whether the request results are cached Based on the Cache-Control domain in the http header.
E. Reduce the number of network requests and merge requests on the server.
F. Reduce the number of redirection times
G. The response time of the api server cannot exceed 100 ms.
Google is working on a project to speed mobile Web pages down to 1 second, focusing on https://developers.google.com/speed/docs/insights/mobile
Android Performance Optimization Method
Http://mobile.51cto.com/abased-410785.htm
For some Android projects, the main cause of performance bottleneck is the memory management mechanism of Android. Currently, mobile phone manufacturers are stingy with RAM and are very sensitive to the impact of RAM on the Performance of software fluency, in addition to optimizing the heap memory allocation of the Dalvik virtual machine, we can also forcibly define the memory size of our software. We use the Dalvik provided by dalvik. system. the following example uses the VMRuntime class to set the minimum heap memory:
- private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
- VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);
// Set the minimum heap memory size to 6 MB. Of course, for memory compression, manual GC interference can also be performed.
Bitmap sets the image size to avoid memory overflow OutOfMemoryError.
★When bitmap is used in android, memory overflow is very easy. The following error is reported: Java. lang. OutOfMemoryError: bitmap size exceeds VM budget
● This section is mainly added:
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = 2;
● Eg1: (image retrieval through Uri)
- Private ImageView preview;
- BitmapFactory. Options options = new BitmapFactory. Options ();
- Options. inSampleSize = 2; // The image width and height are 1/2 of the original image, that is, the image is 1/4 of the original image.
- Bitmap bitmap = BitmapFactory. decodeStream (cr
- . OpenInputStream (uri), null, options );
- Preview. setImageBitmap (bitmap );
The above code can optimize memory overflow, but it only changes the image size and does not completely resolve the memory overflow.
● Eg2: (image removal Through PATH)
- Private ImageView preview;
- Private String fileName = "/sdcard/DCIM/Camera/2010-05-14 16.01.44.jpg ";
- BitmapFactory. Options options = new BitmapFactory. Options ();
- Options. inSampleSize = 2; // The image width and height are 1/2 of the original image, that is, the image is 1/4 of the original image.
- Bitmap B = BitmapFactory. decodeFile (fileName, options );
- Preview. setImageBitmap (B );
- FilePath. setText (fileName );
★There are also some Performance Optimization Methods for Android:
● In terms of memory, you can refer to the Android heap memory and customize the size and optimize the heap memory allocation of the Dalvik virtual machine.
● In terms of basic types, Because Java does not have actual pointers, NDK must be used for sensitive operations. What is interesting about this is that Google launches NDK to help game developers. For example, the support of OpenGL ES has been significantly improved, and it is necessary to operate the GUI on the local code.
● Image object optimization. Here we will talk about the destruction of Bitmap objects on Android. You can use the recycle () method to display and let GC reclaim a Bitmap object, the following method can be used for a non-Bitmap, as shown in figure
- If (bitmapObject. isRecycled () = false) // if not recycled
- BitmapObject. recycle ();
● Currently, the system is relatively mentally retarded in supporting animation, which can be used for the interim Effect of regular applications. However, for games, normal artists may be used to unified GIF Processing, currently, the Android system can only preview the first frame of a GIF. You can read Resources in the GIF89 format by using a thread and a self-writing parser in j2s.
● For most Android phones without too many physical buttons, we may need to imagine a good gesture recognition GestureDetector and gravity sensing for control. We usually need to consider noise reduction for misoperation problems.
You can also customize the size of the Android heap memory.
For some large Android projects or games, there is no problem in algorithm processing. The main cause of the performance bottleneck is the memory management mechanism of Android. Currently, mobile phone manufacturers are stingy with RAM, for the smoothness of software, RAM is very sensitive to the performance impact. Apart from the optimization of the heap memory allocation of the Dalvik Virtual Machine mentioned in the Android Development Network last time, we can also forcibly define the memory size of our software. We use the Dalvik provided by dalvik. system. the following example uses the VMRuntime class to set the minimum heap memory:
- private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
- VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);
// Set the minimum heap memory size to 6 MB. Of course, for memory compression, manual GC interference can also be performed. We will refer to the specific application next time.
Optimize heap memory allocation of Dalvik virtual machines
For the Android platform, the Dalvik JavaVM used by its hosting layer can be optimized from the current performance, for example, when developing large game or resource-consuming applications, we may consider Manual Interference with GC and use dalvik. system. the setTargetHeapUtilization method provided by the VMRuntime class can improve the processing efficiency of the program heap memory. Of course, we can refer to the open-source project for specific principles. Here we only talk about the usage: private final static floatTARGET_HEAP_UTILIZATION = 0.75f; VMRuntime can be called during onCreate. getRuntime (). setTargetHeapUtilization (TARGET_HEAP_UTILIZATION.
[Edit recommendations]
Android Performance Optimization Methods
Http://blog.csdn.net/yugui865/article/details/10211595
1. Use hardware acceleration to add android: hardwareAccelerated = "true" to the application in androidmanifest. xml ". However, this can be used only in android 3.0.
2. Set the cache attribute in View. setDrawingCache to true.
3. Optimize your layout. Use the layoutopt command in the tools directory of the Android sdk to check whether your layout needs optimization.
4. dynamically load the View. Use ViewStub to avoid some views that are not often referenced for a long time.
5. Set the background image of the Window in Acitivity to null. GetWindow (). setBackgroundDrawable (null); is the default background of android empty.
6. Use
The layout layers are optimized. Use
To share the layout.
7. View Heap size
8. Use TraceView to view trace function calls. Targeted optimization.
9. Use of cursor. However, you must manage cursor. Do not close cursor every time you open it, because it takes a lot of time to close Cursor. Cursor. require is used to refresh cursor.
10. Use a circular Buffer (the Linked List data structure can be used ). You can set an upper limit on the length of a linked list and update the content of the circular Buffer continuously based on changes in gestures.
11. Use SurfaceView to refresh the UI in the sub-thread to avoid processing and drawing gestures in the same UI thread (common views do this ).
12. Use JNI to place time-consuming processing on the c/c ++ layer.
13. For some operations that can use files, try to use file operations. File Operations are about 10 times faster than database operations.
14. Lazy loading and caching mechanisms. Start a new thread instead of the UI thread for time-consuming operations to access the network.
Memory leakage caused by uncleanup of objects in the collection
We usually add some object references to the collection. When we don't need this object, we didn't clear its references from the collection, so this set will become larger and larger. If the set is static, the situation is more serious.
. Static keyword
When a member variable of a class is declared static, it belongs to the class rather than the object. If we declare a large resource object (such as Bitmap and context) as static, these resources will not be recycled with the collection of objects,
So be careful when defining member variables using the static keyword.
Use a conservative Service
If your application needs to use the service to execute business functions in the background, unless it is ongoing activities (for example, requests data from the server every several seconds) otherwise, do not keep it running in the background. in addition, when your service execution is complete but the stop fails, be careful about the memory leakage caused by the service.
When you start a service, the system always gives priority to service running. this results in low memory application efficiency because the memory used by the Service cannot do other tasks. it also reduces the number of LRU cache processing that the system keeps, reducing the switching efficiency of different apps. currently, when all services are running, the memory is insufficient and the system is not running properly. If the system gets stuck, the system restarts continuously.
The best way is to use IntentSevice to control the service life cycle. When you start a task with intent, the service will automatically stop after all the work is completed.
In android applications, using a resident service is one of the worst memory management methods when you do not need to use a resident service to execute business functions. therefore, do not use services to keep your applications running. this not only increases the risk of application running because of memory restrictions, but also causes the user to detach the application after discovering these abnormal behaviors.
The memory is released when the view is hidden.
When you jump to different applications and your view is no longer displayed, you should release the resources occupied by the application view. in this case, releasing the resources occupied can significantly increase the cache processing capacity of the system and directly affect the user experience quality.
When the onTrimMemory () callback method of the current Activity class is implemented, the user will be notified when leaving the view. this method can be used to listen to the TRIM_MEMORY_UI_HIDDEN level. When your view elements are hidden from the parent view, release the resources occupied by the view.
Note that only when all view elements of your application become hidden can your application receive TRIM_MEMORY_UI_HIDDEN of the onTrimMemory () callback method. this method is different from the onStop () callback method. This method is triggered only when the Activity instance changes to the hidden state or when a user moves to another activity in the application. therefore, although you have implemented onStop () to release activity resources, such as network connections or unregistered broadcast recipients, you should wait until you receive onTrimMemory (TRIM_MEMORY_UI_HIDDEN) otherwise, the resources occupied by the view should not be released. it can be confirmed that if the user enters your application from another activity through the back key, the view resource will remain available and can be used to quickly restore the activity.
Release memory when memory resources are insufficient
The onTrimMemory () callback method at any stage of the application lifecycle tells you that the device memory is getting lower and lower. You can release resources based on the memory shortage level pushed by this method.