iOS 启动时间优化——相关
背景
iOS的启动时间优化有很多相关的文章,本来不打算写,但是总归是自己整理一遍印象更深刻。这里打算从原理-实践-面试相关三个方面来入手。首先要理解APP启动的原理,启动做了什么?然后针对启动过程中的事件哪些是开发可以进行优化的,去实践?最后则是,面试相关,与启动优化相关的面试有很多,笔者打算列举一下,分别涉及到启动的哪些问题。
启动原理
启动分为冷启动和热启动。冷启动指的是APP进程被杀掉后,从零打开;热启动指的是,APP进入后台,再切换到前台唤起到过程。这里通常说的启动优化,指的是冷启动优化。(Ps: 这里某些版本会出现,刚杀掉的APP,立即再次打开,会直接闪退的问题,是系统的Bug)。
冷启动的过程分为main函数之前(pre-main)
和main函数之后
两个阶段。
pre-main阶段
就如很多文章说的:
pre-main阶段的过程分为dylibs loading
——> rebase/binding
——> ObjC setup
——> initializer
四个部分。每个部分吧啦吧啦…但每次问到这个时候,死记硬背出来真的累人😂。
为什么会感觉困难呢?是因为不知道这四个步骤哪里来的,所以只能背,笔者记忆不好,终归是“不算年轻了”。
所以除了死记硬背,还能怎么办呢?去实践,然后理解,做过了的事情才印象深刻。
所以来看,如何实践&理解:
先打开Xcode的Scheme,然后在Run的选项下,选中Environment Variables
,添加Name为DYLD_PRINT_STATISTICS
,Value为1
。如下:
然后运行一次,会发现控制台中打印出了类似如下的信息:
1 |
|
这里面的信息仔细对比:其中Total pre-main time
指的是pre-main
的总时间;
Total pre-main time
≈ dylib loading time
+ rebase/binding time
+ ObjC setup time
+ initializer time
;
slowest intializers
中的libMainThreadChecker
,是因为Scheme中的Main Thread Checker
打开了,关闭即可,如下的地方勾选去除即可。
所以pre-main
阶段发生了什么?就是发生了dylib loading
、rebase/binding
、ObjC setup time
、initializer time
。这样就知道了这4个步骤的来历,接下来再看看这几个步骤都是做什么的?
翻译如下:
Total pre-main time
指的是pre-main
的总时间- 加载所有依赖的动态库;
- 修正
DATA
中的指针偏差; - 初始化所有对象。
dylib loading time
:- 加载app依赖的库
- 加载库依赖的库
rebase/binding time
:- rebasing: 调整镜像的指针
- binding: 设置指针到外部镜像
ObjC setup time
:- 注册objc类(class registration);
- Category方法插入;
- 保证每个Selector唯一;
initializer time
:
main函数之后的优化,也要多注意,大家都知道application:didFinishLaunchingWithOptions:
是启动时初始化的方法,那这里应该做些什么?
首先问大家一个问题
启动优化实践
application:didFinishLaunchingWithOptions:
中return YES
之前写一个sleep(10);所以只要这个方法不返回,界面就会显示LaunchScreen
,即使已经初始化了首页设置了rootVC也不会显示。
面试相关
+initialize、+init、+load什么时候调用、调用顺序?
+initialize、+load的区别?
+load的加载是在main函数之前?还是之后?
参考
Reducing Your App’s Launch Time
optimizing_app_startup_time
iOS深思篇 | 启动时间的度量和优化