iOS启动优化

一.app冷热启动

APP热启动({

app退出后台,但进程还在系统里;

})

APP冷启动({

APP进程被Kill,重新启动,系统分配一个进程启动APP;

APP启动迟钝,查看主线程是否执行了大文件读写操作、在渲染周期中执行了大量计算等;

})

二.查看APP启动耗时情况

App开始启动后,系统首先加载可执行文件(自身App的所有.o文件的集合),然后加载动态链接器dyld,dyld是一个专门用来加载动态链接库的库。 执行从dyld开始,dyld从可执行文件的依赖开始, 递归加载所有的依赖动态链接库。
动态链接库包括:iOS 中用到的所有系统 framework,加载OC runtime方法的libobjc,系统级别的libSystem,例如libdispatch(GCD)和libsystem_blocks (Block)。

查看方法如下:

Xcode菜单Product-Scheme-edit Scheme...0-Run-Arguments-Environment Variables,添加 DYLD_PRINT_STATISTICS 环境变量,value为1,编译并运行项目输出日志:

Total pre-main time: 539.46 milliseconds (100.0%)//main()总的启动时间

         dylib loading time: 232.89 milliseconds (43.1%)//加载动态库占用

        rebase/binding time:  32.56 milliseconds (6.0%)//指针重定位占用

            ObjC setup time:  22.18 milliseconds (4.1%)//ObjC类初始化占用

           initializer time: 251.68 milliseconds (46.6%)//各种初始化占用

           slowest intializers :

             libSystem.B.dylib :   5.12 milliseconds (0.9%)//intializers初始化最耗时1

    libMainThreadChecker.dylib :  29.74 milliseconds (5.5%)//intializers初始化最耗时2

                      Template : 382.83 milliseconds (70.9%)//intializers初始化最耗时3

三.查看APP启动阶段({

main()执行前;({

  • 【解析Info.plist】:加载信息,例如闪屏;沙盒建立、权限检查
  • 【Mach-O加载】:加载所有依赖的Mach-O文件(递归调用Mach-O加载的方法);加载可执行文件(App 的.o 文件的集合)
  • 【加载动态链接库】:进行 rebase 指针调整和 bind 符号绑定;定位内部、外部指针引用,例如字符串、函数等
  • 【Objc 运行时的初始处理】:包括 Objc 相关类的注册、category 注册、selector 唯一性检查等
  • 【初始化】:执行 +load() 方法,执行声明为attribute((constructor))的C函数,C++静态对象加载

})

程序执行;({

  • 调用 main()
  • 调用UIApplicationMain()
  • 调用applicationWillFinishLaunching   
  • ===优化:
  • 【减少动态库加载】:每个库本身都有依赖关系,使用更少的动态库,并且建议在使用动态库的数量较多时,尽量将多个动态库进行合并。最多可以支持 6 个非系统动态库合并为一个。
  • 【减少+load方法】:方法里的内容可以放到首屏渲染完成后再执行,或使用 +initialize() 方法替换掉。在一个 +load() 方法里,进行运行时方法替换操作会带来 4 毫秒的消耗。
  • 【减少使用】:减少写attribute((constructor))的C函数,控制 C++ 全局变量的数量

})

main()执行后;({

main()函数开始至 appDelegate
didFinishLaunchingWithOptions结束,称为main()函数之后的部分。

主要执行内容

  • 首屏初始化所需配置文件的读写操作;
  • 首屏列表大数据的读取;
  • 首屏渲染的大量计算等。

耗时的影响因素

  • 执行 main()函数的耗时
  • 执行applicationWillFinishLaunching的耗时
  • rootViewController及其childViewController的加载、view及其subviews的加载

})

首屏渲染完成后;({

[首屏渲染完成之后]指的是非首屏其他业务服务模块的初始化、监听的注册、配置文件的读取等。
该阶段指的就是截止到 didFinishLaunchingWithOptions 方法作用域内执行首屏渲染之后的所有方法执行完成。从渲染完成时开始,到 didFinishLaunchingWithOptions方法作用域结束时结束。

})

优化思路一:功能启动优化

main() 函数开始执行后到首屏渲染完成前只处理首屏相关的业务,其他非首屏业务的初始化、监听注册、配置文件读取等都放到首屏渲染完成后去做。

根据刚需分置阶段进行
根据启动流程把刚需功能放置在启动阶段,其他业务功能放在合适的阶段

  • 首屏渲染必要的初始化功能
  • App 启动必要的初始化功能
  • 只需要在对应功能开始使用时才需要初始化的功能
  • 例如:主视图第一时间加载,里面的数据和界面延后加载

优化思路二: 方法启动优化

检查首屏渲染完成前主线程上的耗时方法,将非刚需的耗时方法滞后或异步执行。耗时较长的方法主要发生在计算大量数据的情况下,例如加载、编辑、存储图片和文件等资源。
+load() 方法,一个耗时 4 毫秒,100 个就是 400 毫秒,不可小视

优化三:移除不必要的动态库

移除项目中非必要的动态库

优化四:移除不必要用到的类

代码工程的维护非常重要

优化五:合并功能相似的类和扩展(Category)

由于Category的实现原理,和ObjC的动态绑定有很强的关系,实际上类的扩展是比较占用启动时间的。尽量可能合并一些扩展,并不是让你不使用扩展

优化六:压缩资源图片

图片小了,IO操作量小了,启动就快了。推荐 TinyPNG

优化七:优化applicationWillFinishLaunching

需要在applicationWillFinishLaunching里处理的业务较多时,可以管理起这些任务
将不需要马上在applicationWillFinishLaunching执行的代码延后执行

优化八:优化rootViewController

rootViewController的加载,适当将某一级的childViewController或subviews延后加载
如果你的App可能会被后台拉起并冷启动,可考虑不加载rootViewController

优化九:小优化

  • 不使用xib,直接视用代码加载首页视图
  • NSUserDefaults实际上是在Library文件夹下会生产一个plist文件,如果文件太大的话一次能读取到内存中可能很耗时,如果耗时很大的话需要拆分(需考虑老版本覆盖安装兼容问题)
  • 每次用NSLog方式打印会隐式的创建一个Calendar,因此需要删减启动时各业务方打的log,或者仅仅针对内测版输出log
  • 梳理应用启动时发送的所有网络请求,是否可以统一在异步线程请求

})

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值