对于程序员来说,性能优化是他们工作生涯当中一直所追求的;性能优化分很多种,在这众多种类当中,大家最感兴趣的还是app的启动优化;那么接下来进⼊正题,本⽂将会以iOS App的启动优化为展开点,探讨在哪些阶段可以进行优化。
一、阶段优化项
1.、pre-main阶段
针对 pre-main 阶段做优化时,我们需要先详细了解其加载过程,这个可以在2016年WWDC 的 Optimizing App Startup Time 中详细了解到相关材料
(1) Load dylibs
这⼀阶段dyld会分析应⽤依赖的dylib(xcode7以后.dylib已改为名.tbd),找到其mach-o⽂件,打开和读取这些⽂件并验证其有效性,接着会找到代码签名注册到内核,最后对dylib的每⼀个segment调⽤mmap()。不过这⾥的dylib⼤部分都是系统库,不需要我们去做额外的优化。
优化结论:
① 尽量不使⽤内嵌的dylib,从⽽避免增加 `Load dylibs`开销
② 合并已有的dylib和使⽤静态库(static archives),减少dylib的使⽤个数
③ 懒加载dylib,但是要注意dlopen()可能造成⼀些问题,且实际上懒加载做的⼯作会更多。
(2)Rebase/Bind
在dylib的加载过程中,系统为了安全考虑,引⼊了ASLR(Address Space Layout Randomization)技术和代码签名。由于ASLR的存在,镜像(Image,包括可执⾏⽂件、dylib和bundle)会在随机的地址上加载,和 之前指针指向的地址(preferred_address)会有⼀个偏差(slide), dyld需要修正这个偏差,来指向正确的地址。Rebase在前,Bind在后,Rebase做的是将镜像读⼊内存,修正镜像内部的指针,性能消耗主要在 IO。Bind做的是查询符号表,设置指向镜像外部的指针,性能消耗主要在CPU计算。
优化结论:
在此过程中,我们需要注意的是尽量减少指针数量,⽐如:
① 减少ObjC类(class)、⽅法(selector)、分类(category)的数量
② 减少C++虚函数的的数量(创建虚函数表有开销)
③ 使⽤Swiftstruct(内部做了优化,符号数量更少)
2、main()阶段
在这⼀阶段⾥,主要优化重点放在 SDK初始化、业务⼯具注册、整体didFinishLaunchingWithOptions ⽅法中,因为我们的⼀些第三⽅app⻛格配置、启动引导⻚显示状态逻辑、版本更新逻辑等等基本⽅都会在这⾥进⾏,如果这部分逻辑没有做好优化梳理,随着业务不断拓展,臃肿的业务逻辑会直接导致启动时间加⻓。
优化结论:
在满⾜业务需求的前提下,尽量减少 didFinishLaunchingWithOptions ⽅法在主线程中的事件处理逻辑,⽐如:
① 根据实际业务状况,梳理各个⼆⽅/三⽅库,找到可以延迟加载的库,做延迟加载处理,⽐如放到⾸⻚控制器 的viewDidAppear⽅法⾥。
② 梳理业务逻辑,把可以延迟执⾏的逻辑,做延迟执⾏处理。⽐如检查新版本、注册推送通知等逻辑。
③ 避免进⾏⼀些复杂/多余的计算逻辑,这类逻辑尽量进⾏异步延迟处理。
④ 避免在⾸⻚控制器的viewDidLoad和viewWillAppear做太多容易阻塞主线程的事情,这2个⽅法执⾏完,⾸⻚控制器才能显示。
在实际项⽬中,我们需要对线上项⽬的启动数据进⾏监控,以便及时的定位影响 app 启动时⻓的环节,我们应该怎样更好的处理呢?此时,我们就可以借助工具,比如友盟的U-APM应能性能监测工具 ,只需要我们进⾏简单的pod集成之后,便可根据我们的实际需要进⾏⼿动或者⾃动监控启动数据。
除此之外,我们还可以通过U-APM进⾏崩溃分析、ANR分析、监控告警、卡顿分析、内存分析等等诸多功能,有了U-APM 这个监控平台,在实际开发过程中很⼤程度的提升了我们对线上 app 的分析效率。另外,友盟的“云真机 ”功能也非常完善,很适合开发者朋友们使用;此功能搭载在U-APM应用性能监控平台上,U-APM提供了灵活地测试 *** 作界面,支持ADB调试、WEB远程调试、扫码、抓包、虚拟定位等测试功能,并提供了测试报告供开发者后续查看!这款工具的功能还有很多,对此感兴趣的朋友们不妨尝试一下!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)