360 Mobile Performance Monitoring Practice QDAS-APM (iOS)

Time:2019-8-13

Background

360 is a company that pays attention to user experience. Its slogan is user first. In such a user experience-oriented atmosphere, app performance issues are undoubtedly the focus of attention, but also one of the culprits of user churn. Performance problems mainly include: crash, network request error or timeout, slow UI response, main thread carton, high CPU and memory usage, high power consumption and so on. Most of the problems are due to the misuse of threads, locks, system functions, programming specifications, data structures and so on. The key to solve this problem is to find and locate the problem as soon as possible.

At present, major domestic companies have their own app performance monitoring system, 360 is no exception. In the usual development and user feedback problems, five performance issues are summarized: how to control resource files, how to ensure version quality, how to check online problems, how to prevent performance degradation in the development stage, and whether performance monitoring can truly reflect user experience. At the same time, the functional principle of the relatively perfect performance monitoring platform in the industry was studied. The QDAS-APM, a performance monitoring scheme for 360 on iOS mobile terminals, is obtained.

II. Functions and Principles

QDAS-APM has realized the following function monitoring:

  • Page rendering time
  • Main thread carton
  • network error
  • FPS
  • Large File Storage
  • CPU
  • Memory usage
  • Crash
  • Start-up time

Following is a detailed description of the implementation details and principles according to the functions. In addition, users will perceive performance problems when using app, which can be translated into specific performance monitoring indicators.

(1) Page rendering time

What is the length of page rendering, in fact, is the length of time from page initialization to the user can see the page effect. The indicators to be understood are lifecycle system method execution time, page class name, startup type, execution time and plug-in name. The key metrics are time-consuming execution, and the time consumed by different methods and steps is considered reasonable within the user’s acceptable range. Other indicators are related roles and positioning issues. The direct hook UIViewController method is obviously not feasible because it only works on the UIViewController method, while most apps inherit the UIViewController method.

Here are two possible scenarios:

1. With KVO, we know that the system will help you create a replicate class dynamically when KVO is operated on any object. At the same time, it realizes the coverage and function realization of setter getter function.

2. Use runtime to traverse all classes as subclasses of UIViewController, and then replace them dynamically.

The first is more recommended for compatibility, performance, and IMP that directly accesses subclasses of UIViewController. How to achieve that? Summarize into three steps:

1. A class of UIViewController needs to be created to perform KVO on the instance of UIViewController, with the aim of creating a subclass of UIViewController that needs to be monitored.

2. Adding methods that need to be monitored and adding SEL and IMP corresponding to Swizzle method to subclasses created by KVO. The purpose is to control the timing of invoking methods of the original class.

3. When an instance of UIViewController is destroyed, KVO listeners are removed from the dealloc method, otherwise Crash will occur.

For example, we take the qh_viewDidLoad method as an example:

static void qh_viewDidLoad(UIViewController *kvo_self, SEL _sel)
{
    Class kvo_cls = object_getClass(kvo_self);
    Class origin_cls = class_getSuperclass(kvo_cls);

    // Notes
    IMP origin_imp = method_getImplementation(class_getInstanceMethod(origin_cls, _sel));

    void(*func)(UIViewController *, SEL) =  (void(*)(UIViewController *, SEL))origin_imp;

        CFAbsoluteTime startTime = CACurrentMediaTime();
        func(kvo_self, _sel);
        CFAbsoluteTime endTime = CACurrentMediaTime();
        NSTimeInterval duration = (endTime - startTime)*1000;

    NSLog(@"Class %@ cost %g in viewDidLoad", [kvo_self class], duration);
}

There will be a special case, if the corresponding classes in the KVO generated classes did not implement the monitoring method, then what will happen? The NSKVONotifying_ViewController generated within KVO actually inherits from ViewController, so the corresponding IMP call is taken out directly.

OK, what I mentioned above is the statistics of the execution time of UIViewController class methods. We also want to know how long it takes a user to see the first pin of a page image after a real page jump. Is the sum of the init + loadView + viewDidLoad + viewWillAppear + viewDidAppear methods of the UIViewController class the length of page rendering? The answer is No. Here are three negative examples:

360 Mobile Performance Monitoring Practice QDAS-APM (iOS)

For both asynchronous callback and asynchronous rendering, the execution time of the five methods mentioned above is not applicable. Next, see how to calculate and calculate the program with relative accuracy.

360 Mobile Performance Monitoring Practice QDAS-APM (iOS)

The length of page rendering and layout will be consistent at some point in the future. To get the length of page rendering, you can indirectly refer to the length of page layout completion. There is a method called viewDidLayoutSubviews in UIViewController’s life cycle method. What does it do? It actually tells the controller when the subviews layout is completed. Generally, it will be called twice, and the number of calls varies in different operating system versions.

(2) Carton analysis of main thread

The carton of the main thread directly affects the user’s experience of using, and its performance is influenced by the operation fluency of the page. Firstly, a concept FPS (Frames Per Second) is introduced, which shows the number of frames per second for consecutive pictures. The more frames per second, the smoother the UI operation will be. Generally speaking, keeping the number of frames between 50 and 60 frames per second will give users a sense of fluency, on the contrary, users will perceive Carton. So why is the main thread Carton? First of all, understand the principle of displaying each frame of image to the screen.

This is the principle flow chart of touch screen display. CPU is responsible for computing display content, including view creation, layout calculation, image decoding, text rendering, etc. CPU will submit the calculated results to GPU. GPU will transform, synthesize and render the rendered results to the frame buffer. When the next vertical synchronization signal arrives, the video controller will get from the buffer. Take a view and display it on the screen. Understand the principle of screen display, and then see why it produces Katon.

360 Mobile Performance Monitoring Practice QDAS-APM (iOS)

What is V-Sync mentioned in the diagram, and why should it be introduced into the display process of the iPhone? In the iPhone, there are two buffers in the frame Buffer shown above. The double buffers are introduced to improve the display efficiency, but at the same time, he introduces a new problem. When the video controller has not finished reading, for example, when the screen content is just half displayed, the GPU will have a new frame. After the content is submitted to the frame buffer and the two buffers are exchanged, the video controller will display the lower half of the new frame data on the screen, causing the picture tearing phenomenon. V-Sync is to solve the problem of picture tearing. When V-Sync is turned on, the GPU will send out V-Sync signal on the display to carry out the new frame. Rendering and buffer updates.

After clarifying the principle of the screen display of the iPhone, let’s take a look at why the Karton phenomenon occurs on the iPhone. As mentioned above, CPU and GPU need to complete their own tasks before the image is actually displayed on the screen, and if they miss the next V-Sync (usually 1000/60 = 16.67m) when they finish the task, they will miss the next V-Sync (usually 1000/60 = 16.67m). S), so there will be the display or the content of the previous frame, which is the reason for the interface carton. It is not difficult to find that whether CPU or GPU causes missed V-Sync signal, it will cause interface jamming.

360 Mobile Performance Monitoring Practice QDAS-APM (iOS)

The realization idea of main thread carton monitoring is to open up a sub-thread, then calculate the time consumed between kCFRun Loop BeforeSources and kCFRun Loop AfterWaiting in real time to determine the carton situation of main thread, and then collect stack information and related indicators of current main thread. The report is then submitted to the server for processing, and the final report is generated. The refresh frequency of FPS is very fast and it is prone to jitter. It is difficult to detect Carton directly by comparing FPS. The main thread carton monitoring will also jitter, so a comprehensive scheme is proposed, which combines the main thread monitoring, FPS monitoring and CPU utilization as the criterion to judge carton.

(3) Network monitoring

Network monitoring is usually realized by NSURLProtocol and code injection (Hook). As NSURLProtocol is the upper interface, it is more convenient to use. NSURLProtocol belongs to the system of URL Loading System. The protocol support of application layer is limited, and only supports FTP, HTTP, HTTPS and other application layer protocols. However, traffic using other protocols is helpless, so there are some limitations. CFNetwork, which monitors the underlying network library, does not have this limitation. Certificate validation with HTTPS locally is not suitable for NSURLProtocol. It is easy to cause the loss of business data.

NSURLProtocol

360 Mobile Performance Monitoring Practice QDAS-APM (iOS)
The above figure is based on the NSURLProtocol protocol, which is inherited from NSURLProtocol and registered. The indicators related to network requests are obtained by proxy and self-method.

HOOK-NSProxy

NSProxy is an abstract superclass defining an API for objects 
that act as stand-ins for other objects or for objects that don’t exist yet. 
Typically, a message to a proxy is forwarded to the real object or causes the proxy to load (or 
transform itself into) the real object. Subclasses of NSProxy can be used to implement transparent 
distributed messaging (for example, NSDistantObject) or for lazy instantiation of objects that are expensive to create.

The above paragraph is the definition of NSProxy given by Apple’s official document. NSProxy, like NSObject, is a root class. It is an abstract class that can be forwarded to another instance by inheriting it and rewriting – forward Invocation: and – methodSignatureForSelector: methods. In summary, NSProxy is responsible for forwarding messages to the real target proxy class.

So why don’t we need to specify a class name instead of a method swizzling? Because NSURLConnection Delegate and NSURLSession Delegate are specified by the business side and are usually uncertain, this scenario is not suitable for using Method swizzling. NSProxy can be used to solve the problem. Specific implementation: proxy delegate replaces the original delegate of NSURLConnection and NSURLSession. When proxy delegate receives a callback, if it is a hook method, proxy implementation will call the original delegate; conversely, the implementation of proxy will call the original delegate through message forwarding. The mechanism forwards the message to the original delegate. The following figure illustrates the whole operation process.

360 Mobile Performance Monitoring Practice QDAS-APM (iOS)
By hooking the key methods of NSURLConnection, NSURLSession and CFNetwork, the reporting indicators are obtained. For specific hook methods, see the following figure.

360 Mobile Performance Monitoring Practice QDAS-APM (iOS)

The relevant indicators obtained in hook method are sorted out into the required format and reported to the server. The server generates the final report through data processing and disassembly of indicators.

3. Convenience of QDAS-APM in Integration and Use

Because the SDK function basically adopts the active acquisition function, it does not need secondary development, nor does it need to introduce additional system libraries. So it is very convenient to integrate and use. In the integration of sdk, only three steps are needed:

1. Introducing SDK Library

2. Introducing SDK header file

3. Initialize SDK in didFinish Lauching WithOptions of app and pass in appkey.

360 Mobile Performance Monitoring Practice QDAS-APM (iOS)

Reference resources:

American Regiment Herz

IOS Performance Monitoring Scheme

(360 technology original content, reprinted please be sure to retain the two-dimensional code at the end of the text, thank you ~)

About 360 Technology 360 Technology is a technology sharing public number created by 360 Technology Team, which pushes technology dry goods content every day.
More Technological Information Welcome Attention to “360 Technologies” Wechat Public Number

Recommended Today

The method of obtaining the resolution of display by pyqt5

The code is as follows import sys from PyQt5.QtWidgets import QApplication, QWidget class Example(QWidget): def __init__(self): super().__init__() self.initUI() #Interface drawing to initui method def initUI(self): self.desktop = QApplication.desktop() #Get display resolution size self.screenRect = self.desktop.screenGeometry() self.height = self.screenRect.height() self.width = self.screenRect.width() print(self.height) print(self.width) #Show window self.show() if __name__ == ‘__main__’: #Create applications and objects app […]