iOS performance optimization: Instruments use Combat

Source: Internet
Author: User
Tags uikit

iOS performance optimization: Instruments use Combat

Instruments has recently been used to analyze the performance of the entire application. Discover a lot of interesting points, as well as performance optimizations and some techniques for analyzing performance consumption, summarized below.

Instruments Tips for use

About Instruments official has a very useful user to use guide, of course if not accustomed to the official English can be found here in the text translated version of PDF see. Instruments is really a powerful tool, It is extremely convenient to collect data about the performance and behavior of one or more system processes and to keep track of the data generated over time. Different types of data can also be widely collected. The basic use of instrument tools is not described in more details.

1. Overview

The tool can be launched via the Xcode toolbar product->profile, and the following interface is started:

instrument overview [via by Chenkai]

When you click on the time Profiler application to start running. You can get the elapsed distribution and percentage for the entire application run. In order to ensure that the data analysis in the unified use of the scene really implemented there are the following points to note:

When you start your application performance analysis, be sure to use a real machine that runs on your Mac, but the CPU on your Mac tends to be faster than your iOS device. Instead, the GPU on the Mac is completely different from the iOS device, and the emulator has to emulate the device's GPU at the software level (CPU), which means that GPU-related operations run slower on the emulator, especially when using Caeagllayer to write some OpenGL code. This results in the performance data of the simulator and the user's real-life performance data.

Another important thing before starting performance analysis is that the application must be running to publish the configuration instead of the Debug configuration .

When the release environment is packaged, the compiler introduces a series of optimizations that improve performance, such as removing debug symbols or removing and re-organizing the code. Another iOS introduces a "Watch dog" [watchdog] mechanism. In different scenarios, the watchdog monitors the performance of the application. If the elapsed time specified by the scenario is exceeded, the watchdog forces the process to terminate the application. Developers can crashlog see the corresponding log. But Xcode disables Watch dog under Debug Configuration.

2.Time Profiler

Select Time Profiler to start.

The time profiling tool is used to detect application CPU usage. You can see that the various methods in the application are consuming CPU time. Using a large number of CPUs is not necessarily a problem. The path of a weather animation [like heavy rain] in a different scenario in our client is very high on the CPU, Animation itself is also a very demanding and resource-intensive task.

Click Record to start running.

Time profile Analysis interface [via by Chenkai]

When we first got the analysis data, it was always like this:

performance data [via by Chenkai]

Here is the full path to the execution code, where the system and the application itself have some call paths that are completely pinched together. It's completely invisible. The actual code execution time in the application we care about and where the code path actually resides. Simple way to quickly tick the right call tree separate The thread and hide System libraries two options [explanation of option effect later]:

Post-split performance data [via by Chenkai]

You can see the direct path to the application's various method calls, eliminating the system-related methods and the reverse call tree path. A lot more refreshing. If this is not intuitive enough, choose any time-consuming method branch [here Select Weatherviewcontroller Viewdidload] Double-click Enter to see:

Code & Time-consuming details

You can directly navigate to the code of the Viewdidload, or you can visually see the change method to reduce the time spent in other ways. Similar to [self Loadcityweatherscroollerview] time is 121x, X is a time-consuming unit here for Ms milliseconds. Of course, if you find the problem directly in instrument, it is inconvenient to modify, You can directly click the Xcode button in the upper right to directly locate the Xcode corresponding call method entry. This makes it easy to quickly locate the most CPU-intensive method of code. You can also open Xcode to quickly modify and rerun the profile to see how the changes are time-consuming before and after comparison. Simple and convenient.

The right call Tree option here is necessary to explain [official User Guide translation]:

separate by thread: thread separation is the only way to clearly see the most CPU-consuming threads in the call path.

Invert call Tree: keeps track of stack information from top to bottom. This option allows you to quickly see how the method invocation path takes CPU time, such as Funca{funb{func}}, and check the stack to c->b-> A the deepest c of the call is displayed at the outermost level.

Hide Missing Symbols: If dSYM can not find your app or call the system framework, then the table will see the call method name only see 16 binary values, check this option to hide these symbols, easy to simplify the analysis of data.

Hide System Libraries: This is even more useful, the time-consuming call path will only show the app's time-consuming code, Performance analysis Generally, we compare our own code with time-consuming rather than systematic. Basic is a must option. Note that some code time-consuming is also included in the system level, which can be useful for checking the execution path before and after a tick.

No further information on other methods.

Performance Analysis & Code optimization

Our performance optimization is mainly for the following two usage scenarios:

A: The first time the application starts to enter the weather first page.

B: From the backstage cut to the front desk weather page occupy time.

Until the performance analysis data has not yet been obtained, it has been thought that the first start-up time is mainly wasted appdelegate on the third-party framework initialization [similar to the Weibo&wechat-related SDK initialization call]. When we get the actual performance data time consuming ratio, we find that this is not the case:

Startup time-consuming

As can be seen on the application start initialization work is mainly in mjappdelegate the following two ways to expand: Willfinishlaunchingwithoptions and Didfinishlaunchingwithoptions, The third-party framework initialization work is mainly done in willfinishlaunchingwithoptions. and the actual time-consuming ratio is very small. The basic can be negligible.

And we want to optimize two start-up time scenarios, different. The first entry requires a beginner tutorial, adding cities, requesting city data, parsing data, initializing weather home UI elements, and loading scene animations. When entering from the background, the weather data is parsed from the local storage dt file, the weather first page UI element is initialized, and the weather animation is loaded.

1.NSDateFormatter Problem Highlights

Focus on this point to analyze application start-up & Weather page time-consuming. In AB Two scenarios all found loading the first page element found the following problem:


NSDate (Timeago) getdatestrbytimezone time-consuming

Continue tracking Discovery:


NSDate Time consuming

When loading Mjlinechartview and Tendencychartview in the AB two scenarios, it is time consuming to get the timezone corresponding times. And time consuming is mainly on Getdatestrbytimezone this method call.


Getdatestrbytimezone method

Where creating a NSDateFormatter object takes an average of about 33MS The 3 properties that are set NSDateFormatter average time is about 30ms. Because the first 24-hour weather and the next few days of forecast. It takes time to iterate through the data in the for loop, causing the method not to repeat the call multiple times.

For this issue:

The NSDateFormatter object itself is very slow to initialize, as is the case with Nscalendar. However, it is unavoidable to use them in some usage scenarios, such as JSON data parsing. Using this object while avoiding performance overhead, A good way to do this is by adding a property (recommended) or by creating a static variable to keep the object initialized only once, and be reused multiple times. It is worth mentioning that setting a NSDateFormatter property speed is almost as slow as creating a new instance Object!

Here's how to add attributes:


Attribute mode

For nsdateformatter time overhead out of reuse objects, try to avoid using them to handle multiple date formats. Of course, for date format processing if you need to increase speed, you can use C directly, you can use a third-party library to circumvent this problem.

2.UIImage Cache Trade-offs

You see a lot of code in the project code using the following:


UIImage use

In the main thread, it is found that the image IO overhead and time-consuming ratio in different animation scenes is mixed, and it takes a certain proportion to spend more time on uiimage elements. The memory overhead will also increase significantly.

UIImage loading pictures In general There are two ways:

A:imagednamed initialization

B:imagewithcontentsoffile initialization

The difference is that the imagenamed default loading of the image will cache the image in memory, and this method finds and returns a picture object in the system cache with a specified name. If the corresponding picture object is not found in the cache, load the picture from the specified place and then cache the object and return the picture object .

The Imagewithcontentsoffile only loads the picture, not the cache.

The large use of the Imagenamed method adds additional overhead to the CPU in places where it does not need to be cached. When the application needs to load a larger picture and use a one-time, then there is no need to cache this picture, with Imagewithcontentsoffile is the most economical way , so that the CPU will be wasted too much time on the unnecessary cache one by one because of the uiimage element.

When using the scene to be programmed, it should be differentiated according to the actual application scenario, although the uiimage is small, but the use of elements more problems will be highlighted.

3. Weather Homepage Loading Policy

Comparative analysis of performance data in AB Two scenarios reveals:


Weather Home Weatherview Update time-consuming

Weather Home Weatherview Initialization time has been 300ms-450ms between, occupy a large part of the home page time. And always fixed overhead. Occupy one of the main Thread3 points.

And the user enters first to see is the top half of the weather first part:

Upper part

The lower part requires scrolling to see the bottom half. And does not necessarily trigger:

Lower half

And now the entire home view of the initialization and update all put to the main thread to do. where Weatherinfoview The Updateallinfo method update takes the longest time. More view means more rendering, which means more CPU and memory consumption, which is more so for our weather home in Uiscrollview nested a lot of view.

For this scenario, do not host too many operations on the main thread. Uikit rendering, the user input response needs to be completed on the main process. The main thread is affected by unexpected block or load response time too much will affect the user experience. And for resource consumption too large operation, the principle is to minimize the main thread of CPU consumption, will work " Move away from the main thread, and do not block the main thread. Similar to local some IO is completely moved to other threads to do.

During the commissioning of the time Profiler, it is possible to block the main thread even if it takes up a very few CPU times (if you see the data in the timing Profiler). disks, networks, Lock, Dispatch_sync, and sending messages to other processes/threads all block the main thread. Time Profiler can only detect stacks that consume too much CPU, but it does not detect problems with these IO. It's weird. In system trace, the CPU time is very low, but wait time is very high, indicating that the main thread processing i/ O has severely compromised the performance of the app, and this time consider optimizing the operation.

And for our application home page UI in multiple view, in the loading strategy can be fully multi-threaded synchronous loading, only the upper part of the main thread to load, You can open a thread at the same time to synchronize the load. This can greatly reduce the group thread initialization and update time, when the first page initialization has been rendered, the second half is actually another thread has finished processing.

Also for a single view try not to viewwillappear time-consuming operation, viewwillappear before the view display is called, for efficiency considerations, in this method do not deal with complex time-consuming things; You should only set the view in this method Simple things like background color, font, and so on. Otherwise, the user will obviously feel a dull view display.

4: Apply first load time

To apply the first boot load operation:

First load

The first load sits with the following actions:

A: Link and load: You can display the Dyld in time profile, the library is mapped to the address space, and the bindings and static initialization are completed.

B:uikit initialization: If the app's root View controller is implemented by Xib, it will also be initialized at startup.

C: Apply callback: Call Uiapplicationdeleagte callback: Application:didfinishlaunchingwithoptions.

D: First Core animation call: Call Ca::transaction::commit in the start-up method-[uiapplication _resportapplaunchfinished] to make the first frame drawing.

The first time the application is loaded in the Start method willfinishlaunchingwithoptions and Didfinishlaunchingwithoptions only do the applications that are required for the first start of the operation, and for _dyid_ Start operation in the Initialize Library framework function. Unnecessary framework do not link to avoid time-consuming first load.

Summary as above. A lot of local code calls and the underlying mechanism is not particularly clear, the summary of the optimization of the part is really limited, such as the above for your reference only. In addition, instruments is indeed a powerful tool for analyzing code. There is no third-party tools available to replace it.

iOS performance optimization: Instruments use Combat

Related Article

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.