iOS项目启动时间优化

2020-04-04  本文已影响0人  iOS_小胜

背景

项目功能越来越复杂化,影响到启动时间(主要是感觉自己菜,需要学习)

APP启动时都干了什么事

一般情况下,App 的启动分为冷启动和热启动,我们这里说的是优化冷启动时间。

冷启动是指, App 点击启动前,它的进程不在系统里,需要系统新创建一个进程分配给它启动的情况。这是一次完整的启动过程。

热启动是指 ,App 在冷启动后用户将 App 退后台,在 App 的进程还在系统里的情况下,用户重新启动进入 App 的过程,这个过程做的事情非常少。

一般而言,App 的启动时间,指的是从用户点击 App 开始,到用户看到第一个界面之间的时间。总结来说,App 的启动主要包括三个阶段:
main() 函数执行前;
main() 函数执行后;
首屏渲染完成后。

1.main() 函数执行前

main() 函数执行前的阶段启动时间通过添加环境变量,可以打印出APP的启动时间分析:

(Edit scheme -->Run -->Arguments -->Environment Variables)
添加一项:Name为DYLD_PRINT_STATISTICS,Value为1,然后运行项目查看日志

Total pre-main time: 348.75 milliseconds (100.0%)
         dylib loading time: 302.06 milliseconds (86.6%)
        rebase/binding time: 126687488.9 seconds (135339814.9%)
            ObjC setup time:  17.65 milliseconds (5.0%)
           initializer time:  50.90 milliseconds (14.5%)
           slowest intializers :
             libSystem.B.dylib :   5.88 milliseconds (1.6%)
    libMainThreadChecker.dylib :  32.44 milliseconds (9.3%)

在 main() 函数执行前,系统主要会做下面几件事情(对照上面代码看):

对应的启动速度优化:

2.main() 函数执行后启动时间

main() 函数执行后的阶段,指的是从 main() 函数执行开始,到 appDelegate 的 didFinishLaunchingWithOptions 方法里首屏渲染相关方法执行完成。

首页的业务代码都是要在这个阶段,也就是首屏渲染前执行的,主要包括了:

很多时候,开发者会把各种初始化工作都放到这个阶段执行,导致渲染完成滞后。更加优化的开发方式,应该是从功能上梳理出哪些是首屏渲染必要的初始化功能,哪些是 App 启动必要的初始化功能,而哪些是只需要在对应功能开始使用时才需要初始化的。梳理完之后,将这些初始化功能分别放到合适的阶段进行。例如地图,支付,统计,推送等功能的注册,有些是必须放在appDelegate中注册,有些可以放在首屏渲染完成之后注册,或者有些可以放在子线程注册。

3.首屏渲染完成后

首屏渲染后的这个阶段,主要完成的是,非首屏其他业务服务模块的初始化、监听的注册、配置文件的读取等。从函数上来看,这个阶段指的就是截止到 didFinishLaunchingWithOptions 方法作用域内执行首屏渲染之后的所有方法执行完成。
这个阶段就是从渲染完成时开始,到 didFinishLaunchingWithOptions 方法作用域结束时结束。这个阶段用户已经能够看到 App 的首页信息了,所以优化的优先级排在最后。但是,那些会卡住主线程的方法还是需要最优先处理的,不然还是会影响到用户后面的交互操作。

功能级别的启动优化

功能级别的启动优化,就是要从 main() 函数执行后这个阶段下手。
优化的思路是:main() 函数开始执行后到首屏渲染完成前只处理首屏相关的业务,其他非首屏业务的初始化、监听注册、配置文件读取等都放到首屏渲染完成后去做。

其他小优化

方法级别启动优化

检查首屏渲染完成前主线程上的耗时方法,将非刚需的耗时方法滞后或异步执行。耗时较长的方法主要发生在计算大量数据的情况下,例如加载、编辑、存储图片和文件等资源。
比如+load() 方法,一个耗时 4 毫秒,100 个就是 400 毫秒。ReactiveCocoa 框架每创建一个信号都有 6 毫秒的耗时。这样,稍不注意各种信号的创建就都被放在了首屏渲染完成前,进而导致 App 的启动速度大幅变慢等。

目前来看,对 App 启动速度的监控,主要有两种手段。

第一种方法是,定时抓取主线程上的方法调用堆栈,计算一段时间里各个方法的耗时。

Xcode 工具套件里自带的 Time Profiler ,采用的就是这种方式。开发类似工具成本不高,能够快速开发后集成到你的 App 中,以便在真实环境中进行检查。

对于定时时间间隔的控制

第二种方法是,对 objc_msgSend 方法进行 hook 来掌握所有方法的执行耗时。

Hook:在原方法开始执行时换成执行其他指定的方法,或者在原有方法执行前后执行你指定的方法,来达到掌握和改变指定方法的目的。
hook objc_msgSend 这种方式的优点是非常精确,而缺点是只能针对 Objective-C 的方法。对c方法和block需要借助第三方框架处理,编写维护成本高。

检查方法耗时的工具

推荐使用工具SMCallTrace
友情提示:需要在SMCallTrace.m中打开第54行的注释。

自主实现时间检测工具

实现VC耗时检测

学习笔记,参考多位大神,感谢大神分享!

未完待续...

上一篇下一篇

猜你喜欢

热点阅读