添加启动时间检测
选择Target->Edit Scheme->Run->Environment Variables,添加DYLD_PRINT_STATISTICS
然后启动commond+R运行程序,Consle中可看到以下信息
Total pre-main time: 8.4 seconds (100.0%)
dylib loading time: 5.7 seconds (68.3%)
rebase/binding time: 8.42 milliseconds (0.0%)
ObjC setup time: 66.53 milliseconds (0.7%)
initializer time: 2.6 seconds (30.8%)
slowest intializers :
ImageIO : 392.83 milliseconds (4.6%)
libLLVMContainer.dylib : 235.37 milliseconds (2.7%)
VideoplayerJXJY : 1.7 seconds (20.4%)
Total pre-main time表示的是pre-main阶段所用的时间
dylib loading time表示的是动态库加载的时间
rebase time表示修正偏移指针,即ASLR随机值(偏移值)
binding time表示符号绑定,参考FishHook原理解析
ObjC setup time表示OC所有的类的注册
initializer time表示Load方法
slowest intializers表示加载最慢、最耗时的几个操作步骤
VideoplayerJXJY是项目名称
其他都是系统库,也就是这部分内容基本不可以再优化了
dylib loading动态库加载部分的优化
- 系统自带的动态库,苹果都已经做过优化,所以不需要再进行优化
- 手动添加的动态库,苹果建议不要超过6个
rebase/bindingMach-O指向优化
- 难度高,且效果差
ObjC setup类注册优化
- 减少OC的类及文件个数,
20000个OC类可能增加8ms,优化效率低 - 去掉无用的类或文件
initializer
- 懒加载放在init方法中去做\
上面介绍一些基本的启动知识,下面介绍一个具体的方法,启动优化的二进制重排
原理方面就不做详细叙述了,具体请参考 抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15%\
基于 Clang SanitizerCoverage 的方案
在 Clang 10 documentation 中可以看到 LLVM 官方对 SanitizerCoverage 的详细介绍,包含了示例代码。
简单来说 SanitizerCoverage 是 Clang 内置的一个代码覆盖工具。它把一系列以 __sanitizer_cov_trace_pc_ 为前缀的函数调用插入到用户定义的函数里,借此实现了全局 AOP 的大杀器。其覆盖之广,包含 Swift/Objective-C/C/C++等语言,Method/Function/Block全支持。
开启SanitizerCoverage 的方法是:在 build settings 里的 Other C Flags 中添加 -fsanitize-coverage=func,trace-pc-guard。如果含有 Swift 代码的话,还需要在 Other Swift Flags 中加入 -sanitize-coverage=func 和 -sanitize=undefined。所有链接到 App 中的二进制都需要开启 SanitizerCoverage,这样才能完全覆盖到所有调用。
基于 Clang SanitizerCoverage 杨萧玉写了个工具AppOrderFiles。CocoaPods 接入,一行调用生成 Order File。可以在 GayHub 里查看源码:yulingtianxia/AppOrderFiles
参考大神的工具,自己也写了一个,只是将C函数的调用更换成OC版本的,有兴趣的话可以在这里查看