IOS开发入门之iOS实时卡顿监控
凌雪 2018-11-09 来源 :网络 阅读 675 评论 0

摘要:本文将带你了解IOS开发入门iOS实时卡顿监控,希望本文对大家学IOS有所帮助。

本文将带你了解IOS开发入门iOS实时卡顿监控,希望本文对大家学IOS有所帮助。


       

 

iOS实时卡顿监控。在移动设备上开发软件,性能一直是我们最为关心的话题之一,我们作为程序员除了需要努力提高代码质量之外,及时发现和监控软件中那些造成性能低下的”罪魁祸首”也是我们神圣的职责.

众所周知,iOS平台因为UIKit本身的特性,需要将所有的UI操作都放在主线程执行,所以也造成不少程序员都习惯将一些线程安全性不确定的逻辑,以及其它线程结束后的汇总工作等等放到了主线,所以主线程中包含的这些大量计算、IO、绘制都有可能造成卡顿.

在Xcode中已经集成了非常方便的调试工具Instruments,它可以帮助我们在开发测试阶段分析软件运行的性能消耗,但一款软件经过测试流程和实验室分析肯定是不够的,在正式环境中由大量用户在使用过程中监控、分析到的数据更能解决一些隐藏的问题.

寻找卡顿的切入点

监控卡顿,最直接就是找到主线程都在干些啥玩意儿.我们知道一个线程的消息事件处理都是依赖于NSRunLoop来驱动,所以要知道线程正在调用什么方法,就需要从NSRunLoop来入手.CFRunLoop的代码是开源,,其中核心方法CFRunLoopRun简化后的主要逻辑大概是这样的:




   

int32_t __CFRunLoopRun()

 

{

 

    //通知即将进入runloop

 

    __CFRunLoopDoObservers(KCFRunLoopEntry);

 

      

 

    do

 

    {

 

        //   通知将要处理timer和source

 

        __CFRunLoopDoObservers(kCFRunLoopBeforeTimers);

 

        __CFRunLoopDoObservers(kCFRunLoopBeforeSources);

 

          

 

        __CFRunLoopDoBlocks();    //处理非延迟的主线程调用

 

        __CFRunLoopDoSource0(); //处理UIEvent事件

 

          

 

        //GCD dispatch main   queue

 

        CheckIfExistMessagesInMainDispatchQueue();

 

          

 

        // 即将进入休眠

 

        __CFRunLoopDoObservers(kCFRunLoopBeforeWaiting);

 

          

 

        // 等待内核mach_msg事件

 

        mach_port_t wakeUpPort =   SleepAndWaitForWakingUpPorts();

 

          

 

        // Zzz...

 

          

 

        // 从等待中醒来

 

        __CFRunLoopDoObservers(kCFRunLoopAfterWaiting);

 

          

 

        //   处理因timer的唤醒

 

        if (wakeUpPort == timerPort)

 

            __CFRunLoopDoTimers();

 

          

 

        //   处理异步方法唤醒,如dispatch_async

 

        else if (wakeUpPort ==   mainDispatchQueuePort)

 

            __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__()

 

              

 

        // UI刷新,动画显示

 

        else

 

            __CFRunLoopDoSource1();

 

          

 

        //   再次确保是否有同步的方法需要调用

 

        __CFRunLoopDoBlocks();

 

          

 

    } while (!stop && !timeout);

 

      

 

    //通知即将退出runloop

 

    __CFRunLoopDoObservers(CFRunLoopExit);

 

}

   

不难发现NSRunLoop调用方法主要就是在kCFRunLoopBeforeSources和kCFRunLoopBeforeWaiting之间,还有kCFRunLoopAfterWaiting之后,也就是如果我们发现这两个时间内耗时太长,那么就可以判定出此时主线程卡顿.

量化卡顿的程度

要监控NSRunLoop的状态,我们需要使用到CFRunLoopObserverRef,通过它可以实时获得这些状态值的变化,具体的使用如下:



   

static void runLoopObserverCallBack(CFRunLoopObserverRef observer,   CFRunLoopActivity activity, void *info)

 

{

 

    MyClass *object = (__bridge   MyClass*)info;

 

    object->activity = activity;

 

}

 

  

 

- (void)registerObserver

 

{

 

    CFRunLoopObserverContext context =   {0,(__bridge void*)self,NULL,NULL};

 

    CFRunLoopObserverRef observer =   CFRunLoopObserverCreate(kCFAllocatorDefault,

 

                                                            kCFRunLoopAllActivities,

 

                                                            YES,

 

                                                            0,

 

                                                            &runLoopObserverCallBack,

 

                                                            &context);

 

    CFRunLoopAddObserver(CFRunLoopGetMain(),   observer, kCFRunLoopCommonModes);

 

}

   

只需要另外再开启一个线程,实时计算这两个状态区域之间的耗时是否到达某个阀值,便能揪出这些性能杀手.

为了让计算更精确,需要让子线程更及时的获知主线程NSRunLoop状态变化,所以dispatch_semaphore_t是个不错的选择,另外卡顿需要覆盖到多次连续小卡顿和单次长时间卡顿两种情景,所以判定条件也需要做适当优化.将上面两个方法添加计算的逻辑如下:



static void runLoopObserverCallBack(CFRunLoopObserverRef observer,   CFRunLoopActivity activity, void *info)

 

{

 

    MyClass *object = (__bridge   MyClass*)info;

 

      

 

    // 记录状态值

 

    object->activity = activity;

 

      

 

    // 发送信号

 

    dispatch_semaphore_t semaphore =   moniotr->semaphore;

 

    dispatch_semaphore_signal(semaphore);

 

}

 

  

 

- (void)registerObserver

 

{

 

    CFRunLoopObserverContext context =   {0,(__bridge void*)self,NULL,NULL};

 

    CFRunLoopObserverRef observer =   CFRunLoopObserverCreate(kCFAllocatorDefault,

 

                                                            kCFRunLoopAllActivities,

 

                                                            YES,

 

<div   class="lin    

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!

本文由 @凌雪 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程