1. App启动过程
解析Info.plist
加载相关信息,例如如闪屏
沙箱建立、权限检查
Mach-O加载
如果是胖二进制文件,寻找合适当前CPU类别的部分
加载所有依赖的Mach-O文件(递归调用Mach-O加载的方法)
定位内部、外部指针引用,例如字符串、函数等
执行声明为__attribute__((constructor))的C函数
加载类扩展(Category)中的方法
C++静态对象加载、调用ObjC的+load函数
程序执行
调用main()
调用UIApplicationMain()
调用applicationWillFinishLaunching
2、测量启动耗时
在Xcode的菜单中选择Project→Scheme→Edit Scheme...,然后找到Run→Environment Variables→+,添加name为DYLD_PRINT_STATISTICS , value为1的环境变量。
main()一共耗时1.2S
其中加载动态库使用106.74ms,
指针重定位使用288.28ms,
ObjC类初始化耗时214.02ms,
各种初始化耗时648.74ms
启动1:
Total pre-main time: 1.0 seconds (100.0%)
dylib loading time: 102.64 milliseconds (9.7%)
rebase/binding time: 323.35 milliseconds (30.6%)
ObjC setup time: 137.37 milliseconds (13.0%)
initializer time: 491.81 milliseconds (46.6%)
slowest intializers :
libSystem.B.dylib : 11.01 milliseconds (1.0%)
HomeApp : 869.17 milliseconds (82.3%)
启动2:
Total pre-main time: 734.51 milliseconds (100.0%)
dylib loading time: 36.44 milliseconds (4.9%)
rebase/binding time: 154.81 milliseconds (21.0%)
ObjC setup time: 91.17 milliseconds (12.4%)
initializer time: 451.90 milliseconds (61.5%)
slowest intializers :
libSystem.B.dylib : 12.00 milliseconds (1.6%)
libBacktraceRecording.dylib : 18.06 milliseconds (2.4%)
HomeApp : 785.59 milliseconds (106.9%)
加载dylib:
所以尽可能把多个内嵌 dylib 合并成一个来加载,或者使用 static archive
Rebase/Binding:
之前提过 Rebaing 消耗了大量时间在 I/O 上,而在之后的 Binding 就不怎么需要 I/O 了,而是将时间耗费在计算上。所以这两个步骤的耗时是混在一起的。
之前说过可以从查看 __DATA 段中需要修正(fix-up)的指针,所以减少指针数量才会减少这部分工作的耗时。对于 ObjC 来说就是减少 Class,selector 和 category 这些元数据的数量。从编码原则和设计模式之类的理论都会鼓励大家多写精致短小的类和方法,并将每部分方法独立出一个类别,其实这会增加启动时间。对于 C++ 来说需要减少虚方法,因为虚方法会创建 vtable,这也会在 __DATA 段中创建结构。虽然 C++ 虚方法对启动耗时的增加要比 ObjC 元数据要少,但依然不可忽视
Objc setup:
大部分ObjC初始化工作已经在Rebase/Bind阶段做完了,这一步dyld会注册所有声明过的ObjC类,将分类插入到类的方法列表里,再检查每个selector的唯一性。在这一步倒没什么优化可做的,Rebase/Bind阶段优化好了,这一步的耗时也会减少。
Initializers:
到了这一阶段,dyld开始运行程序的初始化函数,调用每个Objc类和分类的+load方法,调用C/C++ 中的构造器函数(用attribute((constructor))修饰的函数),和创建非基本类型的C++静态全局变量。Initializers阶段执行完后,dyld开始调用main()函数。
1、减少在App里开发者的动态库集成或者有可能地将其多个动态库最终集成一个动态库后进行导入, 尽量保证将App现有的非系统级的动态库个数保证在6个以内.
2、减少Appp的Objective-C类,分类和的唯一Selector的个数.这样做主要是为了加快程序的整个动态链接, 在进行动态库的重定位和绑定(Rebase/binding)过程中减少指针修正的使用,加快程序机器码的生成.
3、定期扫描不再使用的动态库、类、函数,例如每两个迭代一次
4、使用initialize方法进行必要的初始化工作.用+initialize方法替换调用原先在OC的+load方法中执行初始代码工作,从而加快所有类文件的加载速度.
Home中未用到的类:
Home.h
HomeJumpHandle.h
HomeLocalEntranceCell.h
HomeOperationItem.h
HomeRedEnvelopeInfo.h
SearchBusiness中未用到的类:
Category/NSURL+SafeURL.h
Category/UIButton+FillColor.h
RecommendCard/Cell/SearchAGoodPlaceToGoCell.h
RecommendCard/Cell/SearchSeasonQunarCell.h
RecommendCard/VC/HomeBusinessVC.h
两者差别: