TraceView is an Android platform equipped with a good performance analysis tool. It can be graphically used to let us know the performance of the program we want to track, and can be specific to method. More information: Profiling with Traceview and Dmtracedump
TraceView Introduction
TraceView is an Android platform-specific data acquisition and analysis tool that is used primarily to analyze hotspots for applications in Android. TraceView itself is just a data analysis tool, and data acquisition requires the use of the Debug class in the Android SDK or the use of the DDMS tool. The use of the two is as follows:
- The developer calls the Startmethodtracing function of the Debug class in the Android SDK before starting some critical code snippet and calls the Stopmethodtracing function before the end of the critical snippet. During the run of these functions, the function of all threads of the application (note, Java threads only) will be collected during run time, and the collected data will be saved to a file under/mnt/sdcard/. Developers then need to use the TraceView tool in the SDK to analyze the data.
- With the DDMS tool in the Android SDK. DDMS can capture function call information for a running process in the system. For developers, this approach works for situations where the source code is not applied to the target.
DDMS in TraceView use as follows, the debugger can click on the button by selecting the application in the Devices to Start method Profiling (Open methods Analysis) and click Stop Method Profiling (Stop methods Analysis)
After opening the method analysis to the application of the target page test operation, after the completion of the test Stop method analysis, the interface will jump to the DDMS trace analysis interface, as shown in:
The TraceView interface is complex, and its UI is divided into up to two panels, the Timeline panel (timeline panels) and the profile panel. In the upper part of the Timeline Panel (timeline panel), Timeline panel can be subdivided into two Pane of left and right:
- The left Pane shows the thread information collected in the test data. This test data captures the information of main thread, sensor thread and other system worker threads.
- The Pane on the right shows the timeline, which is the function call information involved in each thread test time period. This information includes the function name, function execution time, and so on. The graph shows that the contents of the Thread-1412 thread are very rich, while the other threads are doing much less work during this time period.
- In addition, developers can move the timeline vertical axis in the timeline Pane. The top of the vertical axis displays the function information that a thread is executing in the current point in time.
The lower half of the section is the profile panel, which is the core interface of TraceView, which is very rich in content. It mainly shows the case of each function call in a thread (select a thread in the Timeline Panel first), including information such as CPU usage time, number of calls, and so on. This information is the key to finding a hotspot. So, for developers, be sure to understand the meaning of the columns in the profile Panel. The following table lists the more important column names and their descriptions in the profile Panel.
TraceView Combat
Now that you're done with TraceView's UI, here's how to use TraceView to find a hotspot. In general, the hotspot includes two types of functions:
- One is a function that has a few calls, but takes a long time each time it is called.
- A class is a function that takes a very long time but is called very frequently.
Test Background : The APP in the test machine after a period of time after the mobile phone hot, slow, high CPU occupancy phenomenon. The application in the background for CPU data monitoring, the results show that even if the application does not take any action, the application of the CPU share will continue to grow.
Follow the methods in the TraceView Introduction to test, TraceView results UI display after the data analysis, in the profile Panel, choose to sort by Cpu Time/call in descending order (from top to end, each item is time-consuming from high to low) to get results:
The Imageloadertools$2.run () in the figure is a function in the application that takes 1111.124 of its time. Then click on the Imageloadertools$2.run () item to get a more detailed call graph:
Parents is the caller of the Imageloadertools$2.run () method: Parents (The methods calling this method); children to Imageloadertools$2.run () Called child function or method: Children (the methods called by this method). In this example, the caller of the Imageloadertools$2.run () method is the Framework part, and the Imageloadertools$2.run () method calls the self-method in which we find that there are three methods of the incl Cpu time% occupancy is up to 1 More than 4%, the more outrageous is that the Calls+recurcalls/total show that the three methods are called more than 35,000 times, from the package name can be identified by the test method for the tester itself, which can be judged by Imageloadertools$2.run () It is very likely that the mobile phone is hot, lag, high CPU occupancy factor.
Code Validation
It is generally possible to judge that there is a problem with the Imageloadertools$2.run () method, and find this method to verify the code:
1 package com.sunzn.app.utils; 2 3 Import Java.io.File; 4 Import java.io.IOException; 5 Import Java.io.InputStream; 6 Import java.lang.ref.SoftReference; 7 Import Java.util.ArrayList; 8 Import Java.util.HashMap; 9 Import Android.content.Context; Import Android.graphics.Bitmap; Import android.os.Environment; Import Android.os.Handler; Import Android.os.Message; public class Imageloadertools {httptools httptool; private Context Mcontext; 21 22 Private Boolean isloop = true; Hashmap<string private, softreference<bitmap>> mhashmap_caches; a private arraylist<imageloadtask> maarraylist_taskqueue; Handler Mhandler = new Handler () {$ public void Handlemessage (Android.os.Message msg) {30 Imageloadtask Loadtask = (imageloadtask) msg.obj; LoadTask.callback.imageloaded (Loadtask.path, Loadtask.bitmap); 32}; 33}; 34 35 Private thread mthread = new Thread () {PNs public void run () {isloop) {40 41 while (Maarraylist_taskqueue.size () > 0) {$ try {. Ageloadtask task = maarraylist_taskqueue.remove (0); if (Constant.loadpictype = = 1) {byte[] bytes = Httptool.get Byte (Task.path, NULL, httptools.method_get); Task.bitmap = Bitmaptools.getbitmap (Bytes, 40, 40); Constant.loadpictype} else if (= = 2) {InputStream in = Httptoo L.getstream (Task.path, NULL, httptools.method_get); Wuyi Task.bitmap = Bitmaptools.getbitmap (in, 1); (Task.bitmap! = null) {MHAs Hmap_caches.put (Task.path, New softreference<bitmap> (Task.bitmap)); 56 File dir = Mcontext.getexternalfilesdir (environment.directory_pictures); if (!dir.exists ()) {dir.mkdirs (); 59 } string[] Path = Task.path.split ("/"); The String filename = path[path.length-1]; A. file File = new file (dir, filename); Bitmaptools.savebitmap (File.getabsolutepath (), task.bitmap); A Message msg = Message.obtain (); Msg.obj = task; Mhandler.sendmessage (msg); (IOException e) {E.printstacktrace (); (Exception e) {e.printstacktrace (); 72} 73 Synchronized (this) {75 try {wait (); interruptedexception} catch ( e) {e.printstacktrace (); 79} 80} 81 82 } 83 84} 85 86}; 87 88}; Imageloadertools Public (context context) {This.mcontext = context; Httptool = new Httpto OLS (context); Mhashmap_caches = new hashmap<string, softreference<bitmap>> (); 94 Maarraylist_taskqueue = new Arraylist<imageloadertools.imageloadtask> (); Mthread.start (); 98 Private class Imageloadtask {path;100 String Bitmap bitmap;101 Callback CA }103 104 Public interface Callback {llback;102 void imageloaded (String path, Bitmap Bitmap); 106}1 108 public void Quit () {109 Isloop = false;110}111 The public Bitmap imageload (STring path, Callback Callback) {113 Bitmap Bitmap = null;114 string[] path1 = Path.split ("/"); 115 String filename = path1[path1.length-1];116 117 if (Mhashmap_caches.containskey (path)) {118 Bitmap = Mhashmap_caches.get (Path). get (); 119 if (bitmap = = null) {mhashmap_caches.remove (path); 121 } else {122 return bitmap;123}124}125 126 File dir = mcontext.g Etexternalfilesdir (environment.directory_pictures); 127 File File = new file (dir, filename); 129 Map = Bitmaptools.getbitmap (File.getabsolutepath ()); 131 if (bitmap! = null) {return bitmap;133 }134 135 Imageloadtask task = new Imageloadtask (); 136 Task.path = path;137 Task.callback = CA llback;138 Maarraylist_taskqueue.add (Task); 139 synchronized (Mthread) {141 mthread.notify ( ); 142}143 144 return null;145}146 147}
The above code is the Imageloadertools picture tool class of all the code, not anxious to study the code implementation of this class, first to see how this class is called:
1 Imageloadertools imageloadertools = Imageloadertools = new Imageloadertools (this); 2 3 Bitmap Bitmap = Imageloadertools.imageload (Picpath, New Callback () {4 5 @Override 6 public void Imag eloaded (String Picpath, Bitmap Bitmap) {7 if (Bitmap = = null) {8 Imageview.setimageresource (r.drawable.default ); 9 } else { imageview.setimagebitmap (bitmap), }12 }13}), if (bitmap = = null) { Imageview.setimageresource (R.drawable.fengmianmoren); n} else { imageview.setimagebitmap (bitmap); 19}
The process of imageloadertools being called is very simple: 1. Imageloadertools instantiation; 2. Execute the Imageload () method to load the picture.
During the instantiation of the Imageloadertools class's constructor (90 rows-96 rows), the network tool httptools initialized, a new picture cache Map is created, a new download queue is created, and the download thread is opened. At this point, note that the operation of the thread is turned on, after the thread is turned on and the Run () method (35 rows-88 rows), the value of Isloop is the default true,maarraylist_taskqueue.size () is 0, in the task queue Maarraylist_ This loop will continue to loop until the download task is taskqueue. When the Imageload () method loads the picture, it will first go to the cache mhashmap_caches to find whether the picture has been downloaded, if it has been downloaded, then directly return the corresponding bitmap resources, if not found will go to Maarraylist_ Add the download task to the Taskqueue and wake up the corresponding download thread, the previously opened thread will enter the download logic after discovering maarraylist_taskqueue.size () > 0, and after the task is finished downloading the corresponding picture resources into the cache mhashmap_caches and updates the UI, the download Thread execution Wait () method is suspended. The business logic of a picture download is so easy to understand that there seems to be no problem. At first I thought so, but later in the process of carefully analyzing the code, I found that if the same picture resource is loaded again, there will be a dead loop. Do you remember the cache mhashmap_caches? If a picture has been downloaded before, there will be a reference to the image in the cache. When reloading the image, if you repeatedly initialize the Imageloadertools, the thread will be turned on, and when the image is loaded using the Imageload () method, the image resource is found in the cache, it will be returned directly, note that this is using the return bitmap; that means that the code that adds the download task to the download queue in the imageload () method will not be executed until the Isloop in the Run () method = True and Maarraylist_taskqueue.size () = 0 so that the logic in the inner while is the key code for the suspended thread wait () never be executed, and the outer while judgment condition is always true, so the program has a dead loop. The dead cycle is the mobile phone perm, lag, high CPU occupancy rateThe real reason lies.
Solution Solutions
With the exact location of the code problem, the solution is simple, and the solution here is to put the wait () method from the inner while loop to the outer while loop, so that when the same picture is repeatedly loaded, the thread is suspended as soon as the dead loop occurs, which prevents the occurrence of a dead loop. The code is as follows:
1 private thread mthread = new Thread () {2 3 public void Run () {4 5 while (Isloop) {6 7 whi Le (maarraylist_taskqueue.size () > 0) {8 9 try {imageloadtask task = Maarrayli St_taskqueue.remove (0); if (Constant.loadpictype = = 1) {byte[] bytes = Httptool.getbyte (Task.path, NULL, httptools.method_get); task.bitmap = Bitmaptools.getbitmap (by TES, Max.), or else if (Constant.loadpictype = = 2) {InputStream in = htt Ptool.getstream (Task.path, NULL, httptools.method_get); task.bitmap = Bitmaptools.getbitmap (In, 1)}19 if (task.bitmap! = null) {mhashmap_caches. Put (Task.path, new softreference<bitmap> (Task.bitmap)), File dir = Mcontext.getexternalfil Esdir (Environment.directOry_pictures); if (!dir.exists ()) {dir.mkdirs (); 25 }26 string[] Path = Task.path.split ("/"); String filename = pa th[path.length-1];28 File File = new file (dir, filename); Bitmaptools. Savebitmap (File.getabsolutepath (), task.bitmap); Message msg = Message.obtain (); 31 Msg.obj = task;32 mhandler.sendmessage (msg); 33}34 } catch (IOException e) {e.printstacktrace (); 37} catch (Exception e) E.printstacktrace ();}39}41 synchronized (this) {4 3 try {interruptedexception} (); catch (e) {46 E.printstacktrace(); 47}48}49 50}51 52};53 54};
Finally, the code after the modification of the code to run the performance diagram, and many times before repeated execution, the efficiency has a qualitative improvement, mobile phone hot, lag, high CPU occupancy phenomenon also disappeared.
[Advanced] Performance analysis tool TraceView