App启动速度优化记录

前因

优化了 App 的启动速度,做个记录。

基础知识

App 的启动总时间 T = T1 + T2 + T3

T1:main函数之前

T2:main函数之后到 didFinishLaunchingWithOptions 方法执行完毕

T3:首页渲染

T1的主要工作有:

1
exe() -> 加载可执行文件 -> 加载 dyld(the dynamic link editor)-> dyld 加载其他动态库 -> Rebase -> Bind -> Objc -> initializer

操作系统首先为 App 进程分配一段内存空间,然后执行以下操作:

  1. 把 App 对应的可执行文件加载到内存
  2. 把 dyld 加载到内存
  3. dyld 进行动态链接

dyld 在各阶段所做的事情:

  1. 加载其他动态库

    dyld 从主执行文件的 header 获取到需要加载的所依赖动态库列表,然后它需要找到每个 dylib,而应用所依赖的 dylib 文件可能会再依赖其他 dylib,所以需要加载的动态库列表是一个递归依赖的集合。

  2. Rebase 和 Bind

    Rebase 在 Image 内部调整指针的指向。在过去,会把动态库加载到指定地址,所有指针和数据对于代码都是对的。而现在地址空间是随机的,所有需要在原来的地址根据随意的偏移量做一下修正。

    Bind 是把指针正确地指向 Image 外部的内容。这些指向外部的指针被符号(symbol)名称绑定,dyld 需要去符号表里查找,找到 symbol 对应的实现。

  3. Objc setup
    注册 Objc 类(class registration)
    把 category 的定义插入方法列表 (category registration)
    保证每一个 selector 唯一 (selector uniquing)

  4. Initializers

    Objc 的 +load() 函数

    C++ 的构造函数、属性函数

    非基础类型的 C++ 静态全局变量的创建(通常是类和结构体)

最后 dyld 会调用 main() 函数,main() 会调用 UIApplicationMain(),befor main() 的过程也就此完成。

影响T1时间的因素:

  1. 动态库加载越多,启动越慢
  2. Objc 类,方法越多,启动越慢
  3. Objc 的 +load 越多,启动越慢
  4. C 的 constructor 函数越多,启动越慢
  5. C++ 动态对象越多,启动越慢

T2的主要工作有:

各类 SDK 初始化,H5 资源包下载,数据库配置等操作

影响T2时间的因素:

一些可以延后初始化的 SDK / 下载的操作全都堆在 didFinishLaunchingWithOptions 方法里

T3的主要工作有:

请求网络数据,渲染首页 UI

影响T3时间的因素:

网络请求,页面渲染

具体实践

T1

  1. 指定辅助 pod 库在 Debug 环境下运行

    1
    2
    pod 'MLeaksFinder', :configurations => ['Debug']
    pod 'FLEX', :git => 'https://github.com/36Kr-Mobile/FLEX.git', :commit => '49cb9e9e6ee29f48f4ebbc4810817ef4ad1e208a', :configurations => ['Debug']
  2. 去掉项目中过期类文件、方法、宏定义等

在 Edit Scheme —> Run —> Arguments —> Environment Vaiables 里添加 DYLD_PRINT_STATISTICS 为1可以看到 main 函数之前的执行时间

scheme.jpg

优化前:

优化前.jpg

优化后:

优化后.jpg

T2

把一些非必要的 SDK 放在首页渲染后再进行初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// MARK: 延后注册的 SDK
fileprivate func delayRegisterSDK() {
delay(2.0) {
// 初始化友盟
self.setupUMeng()

// 支付模块
self.setupIAP()

// 配置缓存数据库等
self.configCache()
self.updateRealmVersion()

// 系统配置的东西
self.fetchServiceInfo()

...
}
}

T3

把网络请求提前,放在开屏广告页请求

最后

优化前视频

优化后视频

推荐资料

美团外卖iOS App冷启动治理

今日头条iOS客户端启动速度优化