为什么80%的码农都做不了架构师?>>>
App启动过程
解析Info.plist
加载相关信息,例如如闪屏
沙箱建立、权限检查
Mach-O加载
如果是胖二进制文件,寻找合适当前CPU类别的部分
加载所有依赖的Mach-O文件(递归调用Mach-O加载的方法)
定位内部、外部指针引用,例如字符串、函数等
执行声明为__attribute__((constructor))
的C函数
加载类扩展(Category)中的方法
C++静态对象加载、调用ObjC的+load
函数
程序执行
调用main()
调用UIApplicationMain()
调用applicationWillFinishLaunching
测量冷启动耗时:
冷启动比热启动重要
当用户按下home键的时候,iOS的App并不会马上被kill掉,还会继续存活若干时间。理想情况下,用户点击App的图标再次回来的时候,App几乎不需要做什么,就可以还原到退出前的状态,继续为用户服务。这种持续存活的情况下启动App,我们称为热启动,相对而言冷启动就是App被kill掉以后一切从头开始启动的过程。我们这里只讨论App冷启动的情况。
main()函数之前
在不越狱的情况下,以往很难精确的测量在main()函数之前的启动耗时,因而我们也往往容易忽略掉这部分数据。小型App确实不需要太过关注这部分。但如果是大型App(自定义的动态库超过50个、或编译结果二进制文件超过30MB),这部分耗时将会变得突出。所幸,苹果已经在Xcode中加入这部分的支持。
苹果提供的方法
在Xcode的菜单中选择Product
→Scheme
→Edit Scheme...
,然后找到Run
→Environment Variables
→+
,添加name为DYLD_PRINT_STATISTICS
值为YSE
的环境变量。
在Xcode运行App时,会在console中得到一个报告。例如,我在项目中加入以上设置之后,会得到这样一个报告:
如何解读
main()函数之前总共使用了2.8s
在2.8s中,加载动态库用了437.31ms,指针重定位使用了1.6s,ObjC类初始化使用了258.48ms,各种初始化使用了491.03ms。
在初始化耗费的491.03ms中,用时最多的三个初始化是libSystem.B.dylib、libMainThreadChecker.dylib、MediaServices。
多次启动一般越来速度越快,模拟器。。。。时间就像我这个一样,,,,,,,,,,,,,很长
main()函数之后
从main()
函数开始至applicationWillFinishLaunching
结束,我们统一称为main()函数之后的部分。
这部分可以这么测试在main函数中我们加入如下代码:
CFAbsoluteTime startTime;int main(int argc, char * argv[]) {@autoreleasepool {startTime = CFAbsoluteTimeGetCurrent();return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}}
在appdelegate中我们在didfinish中加入
extern CFAbsoluteTime startTime;- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {NSLog(@"starttime %f",CFAbsoluteTimeGetCurrent() - startTime);return YES;}
这样就会得到这段的时间。
优化部分:
main()函数之前耗时的影响因素
动态库加载越多,启动越慢。
ObjC类越多,启动越慢
C的constructor函数越多,启动越慢
C++静态对象越多,启动越慢
ObjC的+load越多,启动越慢
main()函数之后耗时的影响因素
执行main()函数的耗时
执行applicationWillFinishLaunching的耗时
rootViewController及其childViewController的加载、view及其subviews的加载applicationWillFinishLaunching的耗时
优化部分
1. 移除不需要用到的动态库
2. 移除不需要用到的类
3. 合并功能类似的类和扩展(Category)
4. 压缩资源图片
5. 优化applicationWillFinishLaunching
6. 优化rootViewController加载
--尽量避免过多使用+load
方法,可以使用+initlalize
替代
在系统第一次使用到这个类的使用,才会使用到他的+(void)initlalize
方法
--减少- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
里面的操作,在启动页出现后再进行相关操作.(例如放到子线程中去执行)
关于每个objc文件的+load函数的执行循序
每个objc文件都有+load
方法,此处的文件顺序,决定了+load
的执行顺序作者:找不到工作的iOS
链接:/p/d4b9fa8f2585
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
更多可以参考:
https://mp./s/Kf3EbDIUuf0aWVT-UCEmbA
/skyming/iOS-Performance-Optimization