项目日渐庞大,代码越来越烦杂,性能问题也越来越多,准备搞一次系统性的优化。
随着加载项的越来越多,app启动时感觉有很明显的卡顿现象。
要做优化,先得分析APP是如何完成一次启动的
1 | t(App总启动时间) = t1(main()之前的加载时间) + t2(main()之后的加载时间)。 |
So,我们先分析下main()加载之前的过程。
在target
中添加一个value
为1的DYLD_PRINT_STATISTICS
环境变量。
run一哈,控制台输出
1 | Total pre-main time: 532.27 milliseconds (100.0%) |
word妈耶!!! 在main()
执行之前居然就用了532.27ms(需以冷启动的耗时为基准)。
从日志上可以看到大致的过程:
1 | 加载dylib |
根据以上过程能得出影响pre-main()
耗时的主要因素如下
1 | * 动态库加载越多,启动越慢。 |
那么在pre-main()
这一步我们都能做些什么优化工作?
加载dylib
在这一步我们能优化的不多,无非是减少一些动态库的依赖。
Rebase && Bind
因为ASLR的存在,可执行文件在虚拟内存中的地址每次启动都是不同的,所以需要根据偏移量来计算正确的地址。这一步可以优化的点是移除不用的类和减少Catagory和selector的数量。
可以使用FUI来寻找没有使用到的类,也可以使用AppCode来寻找,这里推荐使用AppCode
,能相对安全的移除无效引用和方法等。当然,命中之后也得小心移除,以免出现意外。
上图为未优化前执行结果
上图为优化之后执行结果
经过一系列瞎比操作之后,删除了一些不必要的第三方库,大概移除了70+的无效类,900+无效方法,有些意外的是未使用的属性反而增加了。pre-main
大概优化到了330ms
左右,虽然优化到了推荐的400ms
以内,但还是差强人意,待继续优化。
1 | Total pre-main time: 329.34 milliseconds (100.0%) |
初始化Objective C
上一步优化完之后这里也就没啥可做的了
其它的初始化代码
这一步开始动态调整
使用+initialize替换+load,从而加快所有类文件的加载速度.