Debugging performance with the instruments tool

Source: Internet
Author: User
Tags transparent color

Instruments

Instruments is a tool that is not fully utilized in the Xcode suite. Many iOS developers have never used instruments, or just use the leaks tool to detect circular references. There are actually a lot of instruments tools, including things that are tuned for animation performance.

You can open instruments by selecting the Profile option in the menu (before this, remember to set the target to an iOS device, not an emulator). You will then be shown figure 12.1 (you may have set the simulator option if you don't see all the options).

Figure 12.1 Instruments Tool Options window

As mentioned earlier, you should always set the program as a publishing option. Fortunately, the configuration file defaults to the Publish option, so you don't need to tweak the compilation strategy when analyzing.

Here are a few tools that we'll discuss:

    • Time Analyzer-used to measure CPU usage by method/function interrupts.

    • Core Animation-Used to debug various core Animation performance issues.

    • OpenGL ES driver-used to debug GPU performance issues. This tool is useful when writing open GL Code, but it is sometimes used to handle the work of the core animation.

A great feature of instruments is that it can create our own set of custom Toolsets. In addition to the tools you initially selected, if you open the Library window in instruments, you can drag other tools to the left sidebar. We will create the three tools we mentioned above and then we can use them in parallel (see Figure 12.2).

Figure 12.2 Adding additional tools to the instruments sidebar

Time Analyzer

The Time Analyzer tool is used to detect CPU usage. It can tell us which method in the program is consuming a lot of CPU time. Using a large number of CPUs is not necessarily a problem-you may expect the animation path to be very dependent on the CPU, because animations are often the most demanding tasks on iOS devices.

But if you have a performance problem, looking at CPU time is helpful for judging whether performance is CPU-dependent, and locating the function (see Figure 12.3).

Figure 12.3 Time Analyzer Tool

The time Analyzer has some options to help us navigate to the methods we care about. You can use the check box on the left to open it. The most useful of these are the following points:

    • Detach by thread-this can be grouped by the executing thread. If the code is separated by multithreading, then it is possible to determine which thread is causing the problem.

    • Hide System Library-can hide all of Apple's skeleton code to help us find which piece of code is causing the performance bottleneck. Since we cannot optimize the framework approach, this is useful for locating code that we can actually fix.

    • Show only Obj-c code-hides all code except OBJECTIVE-C. Most of the internal core animation code is in C or C + + functions, so this is useful for us to focus our attention on the methods that we explicitly call in our code.

Core Animation

The core animation tool is used to monitor core animation performance. It gives us a periodic FPS and takes into account the animations that take place outside of the program (see Figure 12.4).

Figure 12.4 Core Animation tool with visual debugging options

The Core Animation tool also provides a series of check box options to help debug rendering bottlenecks:

  • Color Blended Layers-This option makes green-to-red highlighting of mixed areas on the screen based on the degree of rendering (that is, overlays of multiple translucent layers). Because of the reason for repainting, blending has an impact on GPU performance and is one of the culprits for sliding or falling animation frame rates.

  • Colorhitsgreenandmissesred-When using shouldRasterizep attributes, the time-consuming layer drawing is cached and then presented as a simple flat image. This option highlights the rasterized layer in red when the cache is regenerated. If the cache is regenerated frequently, it means that rasterization may have a negative performance impact ( shouldRasterize see Chapter 15th, "Layer performance" for more details on use).

  • Color Copied Images-Sometimes the generation of a homestay image means that the core animation is forced to generate some pictures and then send to the render server instead of simply pointing to the original pointer. This option renders these images blue. Copying pictures is a very expensive operation for memory and CPU usage, so avoid them as much as possible.

  • Color Immediately-Typically the core Animation instruments updates the layer debug colors 10 times per millisecond. For some effects, this is obviously too slow. This option can be used to set up each frame update (which may affect rendering performance and cause frame rate measurements to be inaccurate, so do not set it up all the time).

  • Color misaligned Images-This highlights images that are scaled or stretched and not properly aligned to pixel boundaries (that is, non-integer coordinates). Most of these usually cause the image to scale abnormally, and if you display a large image as a thumbnail or blur the image incorrectly, this option will help you identify the problem.

  • Color offscreen-rendered Yellow-The layers that need to be rendered off-screen are highlighted in yellow. These layers are likely to be used shadowPath or shouldRasterize optimized.

  • Color OpenGL Fast Path Blue-This option highlights any layers that are drawn directly using OpenGL. If you use only Uikit or core animation APIs, you won't have any effect. If GLKView you use or CAEAGLLayer , if you don't show the blue block, it means you're forcing the CPU to render extra textures instead of drawing to the screen.

  • Flash Updated Regions-This option highlights the redrawn content as yellow (that is, any layer drawn with the core graphics at the software level). This kind of drawing is very slow. If this happens frequently, this means there is a hidden bug or there is room to improve performance by increasing the cache or using alternatives.

The options for these highlighted layers are also available in the Debug menu of the iOS emulator (Figure 12.5). We've said before that it's not good to test performance with simulators, but if you can identify where the performance problem is with these highlighting options, then using the iOS emulator to verify that the problem is resolved is more effective than the real-life test.

Figure 12.5 Core Animation visual debug options in iOS simulator

OpenGL ES Driver

The OpenGL ES Drive tool can help you measure GPU utilization, and is also a good indicator for judging and GPU-related animation performance. It also provides a tool that displays FPS like the core animation (Figure 12.6).

Figure 12.6 OpenGL ES Drive Tool

The zip in the sidebar is a series of useful tools. Among the most relevant to core animation performance are the following:

    • Renderer utilization-If this value exceeds ~50%, it means that your animation may have a limit on the frame rate, most likely due to off-screen rendering or repainting caused by excessive blending.

    • Tiler utilization-If this value is more than ~50%, it means that your animation may be limited to geometry, that is, there are too many layers occupied on the screen.

One available case

Now that we are very familiar with the animation performance tool in instruments, we can use it to solve some practical problems in the real world.

We created a simple app that shows a list of simulated contact names and avatars. Note that even if the avatar image exists locally, in order for the app to look more realistic, we load the picture in real time, instead of –imageNamed: preloading it. Also add some layer shadows to make the list appear more realistic. Listing 12.1 shows the implementation of the original version.

listing 12.1 A simple contact list that uses false data

#import "ViewController.h" #import @interface Viewcontroller () @property (nonatomic, strong) Nsarray *items; @property ( Nonatomic, weak) iboutlet UITableView *tableview; @end @implementation viewcontroller-(NSString *) randomName{NSArray *f    Irst = @[@ "Alice" @ "Bob" @ "Bill" @ "Charles" @ "Dan" @ "Dave" @ "Ethan" @ "Frank"];    Nsarray *last = @[@ "appleseed", @ "Bandicoot", @ "Caravan", @ "dabble", @ "Ernest", @ "Fortune"];    Nsuinteger index1 = (rand ()/(double) int_max) * [First Count];    Nsuinteger index2 = (rand ()/(double) int_max) * [last count]; return [NSString stringwithformat:@ "%@%@", First[index1], last[index2]];}    -(NSString *) randomavatar{nsarray *images = @[@ "Snowman", @ "Igloo", @ "Cone", @ "Spaceship", @ "Anchor", @ "Key"];    Nsuinteger index = (rand ()/(double) int_max) * [images count]; return Images[index];}    -(void) viewdidload{[Super Viewdidload];    Set up data Nsmutablearray *array = [Nsmutablearray array]; for (int i = 0; i < i++) {//add Name [array addobject:@{@ ' name ': [Self randomname], @ ' image ': [Self randomavatar]};    } self.items = array; Register cell class [Self.tableview Registerclass:[uitableviewcell class] forcellreuseidentifier:@ "cell"];} -(Nsinteger) TableView: (UITableView *) TableView numberofrowsinsection: (nsinteger) section{return [Self.items count];} -(UITableViewCell *) TableView: (UITableView *) TableView Cellforrowatindexpath: (Nsindexpath *) indexpath{//dequeue    Cell UITableViewCell *cell = [Self.tableview dequeuereusablecellwithidentifier:@ "cell" forindexpath:indexpath];    Load image nsdictionary *item = Self.items[indexpath.row];    NSString *filepath = [[NSBundle mainbundle] pathforresource:item[@ "image"] oftype:@ "PNG"];    Set image and Text cell.imageView.image = [UIImage Imagewithcontentsoffile:filepath];    Cell.textLabel.text = item[@ "name"];    Set image Shadow Cell.imageView.layer.shadowOffset = Cgsizemake (0, 5); Cell.imageView.layer.shadowOpacity= 0.75;    Cell.clipstobounds = YES;    Set text Shadow Cell.textLabel.backgroundColor = [Uicolor Clearcolor];    Cell.textLabel.layer.shadowOffset = Cgsizemake (0, 2);    cell.textLabel.layer.shadowOpacity = 0.5; return cell;} @end

When fast sliding, it will be very card (see figure 12.7 of the FPS counter).

Figure 12.7 sliding frame rate reduced to 15FPS

Intuitively, we suspect that the performance bottleneck should be loaded in the picture. We load images from flash memory in real time, and there is no cache, so this is probably the reason. We can fix it with some great code, and then use GCD to load the picture asynchronously and then cache ... Wait a minute, before you start coding, test the assumptions. First use our three instruments tools to analyze the program to locate the problem. We speculate that the problem may be related to image loading, so try using the Time Profiler tool (Figure 12.8).

Figure 12.8 Analyzing the contact list with the timing profile

-tableView:cellForRowAtIndexPath:The total CPU time utilization is only ~28% (that is, where the avatar image is loaded), which is very low. So the suggestion is that Cpu/io is not really a limiting factor. Then see if it's the GPU problem: detecting GPU utilization in the OpenGL ES driver tool (Figure 12.9).

Figure 12.9 OpenGL ES driver tool shows GPU utilization

The value of rendering service utilization reaches 51% and 63%. It looks like the GPU needs to do a lot of work to render the contact list.

Why is GPU utilization so high? Let's check the screen with the Core Animation Debug Tool option. First open the color blended Layers (Figure 12.10).

Figure 12.10 Debugging a program using the color blended layers option

All the red parts of the screen mean the high-level blending of the character label view, which is normal because we set the background to a transparent color to show the shadow effect. This explains why the rendering utilization is so high.

What about off-screen drawing? Open the color offscreen-rendered yellow option for the Core Animation tool (Figure 12.11).

Figure 12.11 Color offscreen–rendered Yellow options

All table cell content is drawn from the screen. This must be because we add a shadow effect to the picture and the tag view. Disable shadows in your code and see if performance is improved (Figure 12.12).

Figure 12.12 Running a program close to 60FPS after disabling shadows

The problem is solved. After killing the shadow, the slide is smooth. But our contact list doesn't look as good as it was before. How do you keep the shadow effect and not affect performance?

Well, each line of characters and avatars does not need to change when each frame is refreshed, so the layers that appear are UITableViewCell ideal for caching. We can use it shouldRasterize to cache layer content. This will make the layer render once after it is off screen and save the results until the next time you use it (see Listing 12.2).

Listing 12.2 using shouldRasterize improved performance

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath?{    //dequeue cell    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell"                                                                 forIndexPath:indexPath];    ...    //set text shadow    cell.textLabel.backgroundColor = [UIColor clearColor];    cell.textLabel.layer.shadowOffset = CGSizeMake(0, 2);    cell.textLabel.layer.shadowOpacity = 0.5;    //rasterize    cell.layer.shouldRasterize = YES;    cell.layer.rasterizationScale = [UIScreen mainScreen].scale;    return cell;}

We still draw the contents of the layer off the screen, but due to the explicit disabling of rasterization, Core animation caches the results for the drawing, thus improving performance. We can verify that the cache is valid and click the color Hits Green and Misses red option in the Core Animation tool (Figure 12.13).

Figure 12.13 Color Hits Green and Misses Red verifies that the cache is valid

The results are the same as expected-most are green and will blink red when you swipe onto the screen. As a result, the frame rate is now smoother.

So our original idea was wrong. Picture loading is not really a bottleneck, and trying to put it into a complex multiline preempted and cache implementation will be futile. So it's a good habit to verify the problem before you fix it!

Debugging performance with the instruments tool

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.