IOS uses the Instrument-Time Profiler tool to analyze and optimize performance issues

IOS uses the Instrument-Time Profiler tool to analyze and optimize performance issues

background

Not long ago, I made a rich text editing tool. The editor encountered a performance problem when adding multiple pictures. When scrolling the editing area, there would be obvious lag when switching pictures. This article analyzes the performance bottleneck based on this lag performance problem and makes corresponding optimizations.

You can open this link iOS Rich Text Editor Using UITableView to view my article. The project used in this article is also based on this project.

result

The final analysis and optimization results reduced the time from 90ms to 2ms, achieving a relatively smooth effect. Please see below for the specific analysis and optimization steps.

Problem Analysis

Since the problem occurs when the picture is switched, and the picture is placed in a separate Cell, try adding two Logs in the Cell's rendering method cellForRowAtIndexPath to view the time taken for the method to execute.

The corresponding results are:

  1. 2017-08-11 06:12:48.744 RichTextEditDemo[6867:1064632] ====== begin render cell
  2.  
  3. 2017-08-11 06:12:48.749 RichTextEditDemo[6867:1064632] ====== end render cell
  4.  
  5. 2017-08-11 06:12:49.261 RichTextEditDemo[6867:1064632] ====== begin render cell
  6.  
  7. 2017-08-11 06:12:49.266 RichTextEditDemo[6867:1064632] ====== end render cell

Judging from the time of log printing, it only takes a few milliseconds to render each Cell, and it seems that the problem will not occur in this position. However, this is not the truth. Obviously, other places will not be affected, so more advanced analysis tools must be used to analyze and view.

Find the problem

Instrument is a good performance analysis tool that can analyze memory allocation, memory leaks, network conditions, CPU usage and other performance-related issues. The current performance problem is a time-consuming problem, which can be analyzed using Instrument's Time Profiler.

Let this list scroll and switch the image Cell

You can see the following record in the Time Profiler. The red box is the time spent on Cell switching. The increase in this time is obviously higher than other values, so this is where we want to locate.

Tips

  • Alt + Mouse wheel -> Zoom timeline
  • Shift + mouse wheel -> move timeline
  • Hold down the mouse to select -> Select and position the timeline

The first step is to select a range on the timeline and mark this range for analysis to accurately locate the problem, as shown in Figure (1). The second step is to select a function in the stack. Generally, the OC function call is selected. The lower-level function call is implemented in the CF layer in C language, which is difficult to analyze. Therefore, the [UIImage drawInRect:blendMode:alpha] function is selected here for analysis. It can be seen that the time spent on this function call is 92ms, which is a relatively long time, so it should be the cause of the jam.

The time this function takes is related to the size of the image. Select another time peak range, which occurs when switching between small images.

The time consumed in this place is relatively small, but it also reaches 25ms, which has a certain impact on performance.

Solving the problem

From the above analysis, we can conclude that calling the [UIImage drawInRect:blendMode:alpha] function will cause performance problems, because the way UITextView processes images internally is by calling the [UIImage drawInRect:blendMode:alpha] function to draw images.

Since this is the internal processing method of UITextView, the function call behavior cannot be changed by the application layer. However, we can control the UIImage object, or change the display method of the image to achieve the purpose of optimization, so there are the following two solutions.

Solution 1

The first solution is to compress the preview image, then set it to NSTextAttachment, and display it in UITextView

  1. textAttachment.image = self.image;
  2. // ===> Modify to
  3. // scaletoSize is used to compress the original image. The image object in textAttachment is compressed.
  4. textAttachment.image = [self.image scaletoSize:showImageWidth];

After this modification, the scrolling loading time of the large image was reduced to about 40ms

Although the time is reduced by half, 40ms is still relatively long, and we will continue to optimize it below.

Solution 2

The above solution compresses the image, but the time consumption is still due to the call of [UIImage drawInRect:blendMode:alpha] function, so is there a better solution? The answer is yes, you can compress the image passed to UITextView into a very small one (this step is not necessary, just pass an empty UIImageView object, the main reason for setting the image here is that the image area requires an editing cursor), then add a UIImageView to the image area corresponding to UITextView, and set the original image in UIImageView. This solution will be much better than Solution 1.

Several modifications to Option 2:

1. Set the image of NSTextAttachment to an empty UIImage object

  1. //....
  2. NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
  3. CGRect rect = CGRectZero;
  4. rect. size .width = showImageWidth;
  5. rect. size .height = showImageHeight;
  6. textAttachment.bounds = rect;
  7. textAttachment.image = [UIImage new];
  8.  
  9. NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:textAttachment];
  10. //....

2. Add ImageView to Cell to display Image

  1. [self.imageContentView mas_remakeConstraints:^(MASConstraintMaker *make) {
  2. make. left .equalTo(self).offset(_imageModel.imageFrame.origin.x);
  3. make.top .equalTo(self).offset(_imageModel.imageFrame.origin.y);
  4. make.height.equalTo(@(_imageModel.imageFrame. size .height));
  5. make.width.equalTo(@(_imageModel.imageFrame. size .width));
  6. }];

The following is the analysis chart after optimization using Solution 2

As can be seen in the figure, the cellForRowAtIndexPath method takes a total of 2ms. From the analyzed stack, we can see that the UITextView setAttributedText: method only takes 1ms, so this improvement is very obvious. Because an empty UIImageView object is passed, there is no need to execute the [UIImage drawInRect:blendMode:alpha] method. Using UIImageView to directly set the Image method takes almost no time, so the time for the [UIImageView setImage:] method call cannot be seen in the stack.

Summarize

Instrument is a very good tool. You can use it to easily help us locate performance problems. Once the problem is found, it will be easy to find a solution.

<<:  Blockchain technology is open source. What supports BCOS's idea?

>>:  Aite Tribe Story Collection (26): Full Stack Siege Lion's Sunflower Treasure Book

Recommend

Alipay Mini Program officially opens public beta to individual developers

[[258329]] Alipay Mini Program officially opened ...

Building a data-based operation system from scratch

Data-driven operation is a concept that has emerg...

How did the community achieve a growth of 0-500 in 2 months?

The ultimate goal of community operation is to ac...

This article shows you Matsutake mushrooms from around the world

Produced by: Science Popularization China Produce...

Case review + fission methodology | Why is your fission activity ineffective?

I recently chatted with a fellow operations partn...

The popular Nanjing tea drinking exchange group, looking forward to your joining

Nanjing tea drinking exchange group, Nanjing high...