Is your IOS app running at a fast pace? The students in the gun to worry about, performance optimization We have a wonderful trick. With Xcode Home Debugging tool Instruments, pull out those blocking threads, account for memory, consumption of resources, the problem code, completely break down the fan, let the application elated!
For every IOS developer, code performance is a topic to avoid. With the expansion of the project and the increase in functionality, without careful debugging and optimization of the code, either wayward Kaka run, or quietly collapsed ... As a result, everyone is unhappy and the developers are unhappy.
In fact, it is not difficult to break the situation, as long as the monitoring and debugging tools in Xcode Instruments to take some effort, so that the smooth operation of large code is not a myth. Instruments offers a lot of features, and I'll focus on the three categories I use most:
- Time Profiler: Analyze the execution times of the code to find out why the program is slowing down.
- Allocations: monitoring memory usage/distribution
Rapid expansion of memory can quickly kill the program, so be more defensive.
- Leaks: Finding the starting point for a memory leak
Even with the ARC (automatic reference counting) memory management mechanism, the memory leaks caused by circular references are still difficult to avoid in real time, so it is important to be self-reliant at the critical moment.
For these three Tests, I wrote a demo app on GitHub to help you get a more intuitive understanding of how these tools are used. Okay, get to the chase.
Time Profiler
Where did all the time go? Time Profiler can answer. It keeps track of the stack trace for each thread at a set interval (default of 1 milliseconds) and calculates how long a method executes and gives an approximate value by comparing the stack state between time intervals.
In the Demo app first "time Profiler:system methods", I use the Insert sort (insertion sort) and bubble sort (Bubble sort) algorithms for performance comparisons, here's the Swift code:
/* Quoted from: http://waynewbishop.com/swift/sorting-algorithms/*/FuncInsertionsort() {var x, Y, key:IntFor(x =0; x < Numberlist.count; X + +) {key = Numberlist[x]for (y = x; y >-1; y--) {if key < Numberlist[y] {numberlist.removeatindex (y + 1) Numberlist.insert (Key, Atindex:y)}}}}func bubbleSort () {var x, Y, Z, passes, key: int for (x = 0; x < Numberlist.count; ++x) {passes = ( Numberlist.count-1)-X; for (y = 0; y < passes; y++) {key = Numberlist[y] if (Key > Numberlist[y + 1]) {z = numberlist[y + 1] Nu Mberlist[y + 1] = key Numberlist[y] = z}}}
This code is mainly for the addition and deletion of the array, the two methods do not take much time to execute, but the background of the system action is more people dizzying.
You can see that the code uses a lot of indirect dependencies, which are the system library files that support the code to run. Because the processing of large data sets consumes system resources, it is possible to put heavy operations in the background to do the same, the above code will go behind the background thread. As you can see in the call Tree, the called stack name is dispatch_worker_thread3. If you put it on the main thread to execute, the program will definitely hang. Don't believe you comment out Dispatch_async call to see.
Let's take another example of image loading.
Here are three ways to load images:
- LoadSlowImage1: Download a picture from the specified URL (slow loading)
- LoadImage2: Loading a picture from the local repository (note: No system cache is used)
- LoadFastImage3: Loading a picture from the system cache (loading speed is fast)
Let's see if the results from time Profiler are the same as expected.
Go to the demo application The second "time profiler:our methods", click "reload" 10 times to reload the image, so that enough data can be generated to analyze. Then, in the time Profiler diagram, by dragging the mouse to select the area you want to zoom in on, double-click the call from the calling Tree. Reload method that line (highlighted in the row), it jumps to the corresponding line of code, and it is also noted.
See who spends the most time. While the code is nowhere to be optimized, you should recognize the role that caching can play. So even if you sometimes have to call loadslowimage, in most cases the picture is cached, still can save some resources to occupy.
In addition, I would like to say again the option settings for Call Tree.
These options are not selected by default, but selecting them can help you navigate to critical code more quickly, which is often the source of the problem.
- Separate by thread: analysis is done separately by thread, which makes it easier to pull out the problem threads that eat resources. Especially for the main thread, it processes and renders all the interface data, and once it is blocked, the program must stutter or stop responding.
- Invert Call Tree: The reverse output calls the trees. The deepest calling method is displayed at the top, which makes it easier to find the most time-consuming operations.
- Hide Missing Symbols: Hides missing symbols. If the DSYM file or other system architecture is missing, there will be a number of strange hexadecimal values in the list, using this option to mask the interfering elements and let the list return to a crisp.
- Hide System Libraries: Hides the systems library file. Filter out various system calls and show only your own code calls.
- Flattern recursion: Flattening recursion. Combine the multiple stacks produced by the same recursive function (because the recursive function calls itself) into one.
- Top Functions: Find the most time-consuming function or method.
If you need to add additional tools:
Allocations
We often need to download a large number of images from the server, especially for the development of photo class applications. But often a little less attention, memory usage will burst, so make sure to cache these pictures for reuse. Here's an example of memory allocation in the demo program.
As you can see, each time you click "reload" to reload the image, the memory spikes in usage. The application first allocates a lot of memory to replace the original image, and then release the memory, it is conceivable that this operation is not efficient, and if you want to download a larger file, er, the situation will probably lose control.
Take a look at the fourth row of the stack list, there are 9 active pictures in Imageio_png_data, which takes up 12.38 MB of memory, which is not released or cached by the system, causing heap memory allocation to rise. Then look at the effect of using the cache.
After using the cache library (Swift Haneke), point "reload" five times, this time in the Allocations list does not see the Imageio_png_data object, which means that it is empty, there is no image data. Also, the size of all HEAP allocations has been reduced from just 14.61 MB to 2.51 MB. Anonymous VMS (anonymous virtual memory) are part of the available memory that the system reserves for programs that may be reused immediately. To prevent a program from crashing, don't let the heap size grow too fast.
Also, the example uses an asynchronous way to load a picture so that it doesn't have to wait until all the pictures have been downloaded to display in the interface. Most image cache libraries will put loading work in the background to avoid extending the main thread's response period.
Leaks
Although Apple's ARC can be effective against memory leaks, there is a chance of a problem, and Swift is no exception. In view of the limited space, this article does not involve the memory and ARC working principle, can refer to official documents. I'll use code to trigger a memory leak.
First, from the bottom, when two objects establish strong references to each other (strong reference), when an object is freed and another object is not allowed to be released because it is a strongly referenced relationship, ARC cannot determine whether the object that was not released is still in use, resulting in a memory leak.
To solve this problem, you can set the variable in one of the objects to weak and not allow it to appear in the retention cycle. Many developers in the management of the view controller often in the memory leak on the move, thinking that the new controller, the old controller was released to recycle, in fact, not yet. So much code, it will cause many objects are not released. So use this tool to run the entire application, to clean up those strong references to broken chains, it will be beneficial.
In addition to these three types of tools, Instruments also has a lot of practical tools, recommend people according to their own concerns, take some time to learn. Like what:
- Core Data: Monitoring read, cache misses, save and other operations, can be visualized to show whether the number of save more than the actual needs.
- Cocoa layout: Observe the constraint changes and find out the problem with the layout code.
- Network: Tracks TCP/IP and UDP/IP connections.
- Automations: Create and edit test scripts to automate user interface testing for IOS apps.
The last small summary. I do not want to exaggerate the role of Instruments, if the application run quite happily, did not appear what naughty behavior, big can ignore it, wait until the problem to do optimization. For the novice, take some time to understand the function of Instruments, multi-debug multi-accumulation of experience, so that the application in the user experience must not be wrong.
What are some of the Instruments tools you use most? Welcome to share with us.
IOS Performance Optimization: The Instruments tool's life-saving three strokes