前言
作为程序猿来说,“性能优化”是我们都很熟悉的词,也是我们需要不断努以及持续进的事情;其实优化是个很严谨的课题,因为细分来说的话有种优化向 ,但是切忌在实际开发过程中不能盲目的为了优化而优化,这样有时可能会造成适得其反的负效果,需要我们根据实际场景以及业务需求进合理优化。接下来进入正题,本文将会以iOS App的启动优化为展开点进探讨。
启动流程:
iOS App 的启动我们都知道分为pre-main 和 main() 两个阶段,并且在这两个阶段中,系统会进行系列的加载操作,过程如下:
1、pre-main阶段
1. 加载应的可执件
2. 加载dyld动态连接器
3. dyld递归加载应所有依赖的动态链接库dylib
2、main()阶段
1. dyld调 main()
2. 调UIApplicationMain()
3. 调applicationWillFinishLaunching
4. 调didFinishLaunchingWithOptions
阶段优化项
1、pre-main阶段
针对 pre-main 阶段做优化时,我们需要先详细了解其加载过程,这个可以在2016年WWDC 的 Optimizing App Startup Time 中详细了解到, 相关材料
1.1 Load dylibs
这阶段dyld分析应依赖的 dylib (xcode7以后.dylib已改为名.tbd),找到其 mach-o 件,打开和读取这些件并验证其有效性,接着会找到代码签名注册到内核,最后对 dylib 的每个 segment 调 mmap()。不过这的 dylib 部分都是系统库,不需要我们去做额外的优化。
优化结论
1.2 Rebase/Bind
在dylib的加载过程中,系统为了安全考虑,引了ASLR (Address Space Layout Randomization)技术和 代码签名。由于ASLR的存在,镜像(Image,包括可执件、 dylib和bundle)会在随机的地址上加载,和 之前指针指向的地址(preferred_address)会有个偏差(slide), dyld需要修正这个偏差,来指向正确的 地址。 Rebase在前, Bind在后, Rebase做的是将镜像读内存,修正镜像内部的指针,性能消耗主要在 IO。 Bind做的是查询符号表,设置指向镜像外部的指针,性能消耗主要在CPU计算。
优化结论:
1.3 Objc setup
部分ObjC初始化作已经在Rebase/Bind阶段做完了,这步dyld会注册所有声明过的ObjC类,将分类插 到类的法列表,再检查每个selector的唯性。
在这步倒没什么优化可做的, Rebase/Bind阶段优化好了,这步的耗时也会减少。
1.4 Initializers
在这阶段, dyld开始运程序的初始化函数,调每个Objc类和分类的+load法,调C/C++ 中的构造器 函数(attribute((constructor))修饰的函数),和创建基本类型的C++静态全局变量。 Initializers阶段执 完后, dyld开始调main()函数。
优化结论:
2、main()阶段
在这阶段,主要优化重点放在 SDK初始化、业务具注册、整体
didFinishLaunchingWithOptions 法中,因为我们的些第三 app 格配置、启动引导显示状态逻辑、版本更新逻辑等等基本都会在这进,如果这部分逻辑没有做好优化梳理,随着业务不断拓展,臃肿的业务逻辑会直接导致启动时 间加。
场景补充:
另外,在我们实际开发过程中,很多项的控制器都会有些后台可配、较为丰富的结构或者推荐数据 进展示,且我们的展示速度通常也会被纳启动优化的部分,其实对于这种类型的优化,如果我 们还只是传统的 api -> data -> UI 式进的话,就很难有明显的改善空间,因为户的络状态 并不是可控项,如果不做其他处理的话,那在很多场景下对户来说,即使我们放上些占位图,展示的样式也是很不友好的,毕竟控制器对户的第视觉冲击影响还是较的。
对于这种场景下的优化来说,般我们可以采取 Local + Network + Update 的式在定程度上优化 加载速度: 即:
这样做的好处是
当然这种也并不是唯的应对式,且也并对所有场景都适,只是提供种思路已,还是需要根据 项的实际场景选择适合的优化案。
统计时
另外如果在开发过程中,我们想直观的查看 app 启动期间,各阶段的耗时情况,也可以在Xcode,的 edit scheme 设置添加 DYLD_PRINT_STATISTICS 为1 ,打印启动时,例如
优化前启动时:
优化后启动时:
当然,这些log我们仅仅只能在开发调试阶段查看打印,那么在实际项中,我们需要对线上项的启动数据 进监控,以便及时的定位和优化那些影响 app 启动时的环节,这时我们应该怎样更好的处理呢?
当然我们可以通过服务器埋点上报的式统计分析,不过这样来会发现我们的统计成本就会增 加,且结果分析也会变得不那么灵活。所以这推荐种简单的监控式,那就是友盟的 U-APM 应能性 能监控SDK ,只需要我们进简单的pod集成之后,便可根据我们的实际需要进动或者动监控启动数 据,详情可以参考 U-APM, 并且为了便我们对数据进分析,友盟后台已经根据这些数据帮我们绘制出 了对应的分布图,我们可以了然的得出启动耗时分布、启动类型占等等,如图:
除此之外,我们还可以通过SDK进崩溃分析、 ANR分析、监控告警、卡顿分析、内存分析等等诸多功能, 有了 U-APM 这个监控平台,其实在实际开发过程中很程度的提升了我们对线上 app 的优化分析效率。
当然本的介绍也只是较浅显的优化项,仅供参考以及思路引导,优化之路任重道远,还需要我们不断 的去探索、发现、提。不过最后还是要提醒句:在实际项开发过程中,不要为了优化优化,要根据 项情况有针对性的进优化。