WWDC 关于APP启动优化的Session

screenshot.png

本篇是记录一下自己的学习笔记,如有勘误望见谅.

先放上本文的学习来源链接,WWDC 16 和17, 19年 的三个session
优化启动时间 https://developer.apple.com/wwdc16/406
app启动时间:过去,现在,与未来 https://developer.apple.com/wwdc17/413
优化App启动 https://developer.apple.com/wwdc19/423

关于Mach-O和虚拟内存

Execuable(运行时 可执行文件的文件类型)

可执行文件 应用里最重要的二进制文件 也是应用扩展文件的主二进制文件

Dylib(动态库)

Dylib是一个动态库 在其他平台上 用的是你可能会熟悉的名字: DSO和DLL

Bundle(捆绑包)

捆绑包是一种特殊的Dylib 是不能进行链接的 只能在运行时 用dlopen()函数打开它

Image(这里image是指任意上述三种文件)

例如 Dylib,可执行文件

FarmeWork(框架)

这里指 存储该Dylib需要的文件

Mach-O图像格式

screenshot.png

所有的段名都是由大写字母组成

每一段都是页面大小的倍数 图片该例中
TEXT段大小是3页
DATA和LINKEDIT段大小是1页
页面大小由硬件决定 arm64处理器的页面大小是16K, 其他都是4K

一种查看方式是分区 编译器常常会忽略分区 分区是段的子范围


截屏2021-02-27 上午9.24.48.png

分区不用遵循页面的大小 但是它们是不重叠的

最常见的段名是 TEXT DATA LINKEDIT 实际上几乎每一个二进制文件 都包含这三段

TEXT是文件的开头 它包含了Mach的头文件 任何机器指令 以及任何只读常量 比如C字符串
DATA段是重写段 它包含了所有的全局变量
LINKEDIT段 它不包含全局变量的函数 它包含变量函数信息 比如名称和地址
screenshot.png

虚拟内存

虚拟内存解决的问题是 所有这些进程存在时 该如何管理所有物理内存? 所以他们添加了一个小的间接层 每一个进程都是一个逻辑地址空间 映射到RAM的某个物理页面.

这种映射不一定是一对一的 逻辑地址可以不对应任何物理RAM 也可以多个逻辑地址对应 同一物理RAM 这样带来很多种可能 能利用虚拟内存做什么呢? 首先 如果有一个逻辑地址 不映射任何物理RAM 当进程要访问该地址时 就会产生页面错误 内核将停止该线程 并试图找出解决方案

copy on write

内存写时复制. 在所有进程里共享DATA页面
只要进程是只读, 共享内容的全局变量, 但是一旦有进程想要 写入其DATA页面 写入时复制开始 内核会把该页面复制 放入另一个物理RAM并重定向映射 所以该进程有了该页面的副本

screenshot.png

Dylib是如何操作

Dylib必须要做的第一件事 是查看Mach头文件 在内存里 在该进程里 它将查看内存的顶盒, 由于虚拟内存的原因, 启动时那里是空的 没有内容映射到物理页面上 所以产生页面错误 到那时内核意识到 它被映射到了一个文件 所以它将读取文件的第一页放入物理RAM设置其映射 , 
从而使得Dylib可以真正通过 Mach头文件开始读取 
dyld实际上 将进程里面的虚拟内存的 text,data,LINKEDIT 实际的加载到指定的进程中去

App的启动流程 exec() 到main ()

screenshot.png
image.png

Dyld 的工作流程 pro-main 的过程


截屏2021-02-27 上午11.04.58.png

先分析一下启动的时候,发生了什么,

loadDylbs-> bebase -> binding -> initializes -> main
其实启动的步骤就是这几步

screenshot.png

Rebase/Binding 环节的优化

在讲rebase之前,我们需要先讲一下ASLR

ASLR(Address Space Layout Randomization),地址空间布局随机化。在ASLR技术出现之前,程序都是在固定的地址加载的,这样hacker可以知道程序里面某个函数的具体地址,植入某些恶意代码,修改函数的地址等,带来了很多的危险性。ASLR就是为了解决这个的,程序每次启动后地址都会随机变化,这样程序里所有的代码地址都需要需要重新对进行计算修复才能正常访问。

代码地址都需要需要重新对进行计算修复才能正常访问。

出于这个原因,所以我们有了Rebase/Binding

Rebase

什么是Rebase?
rebasing:主要就是调整镜像内部指针的指向。

Binding

Binding: 将指针指向镜像外部的内容。

针对这个环节的优化主要还是以下.

减少OC类的数量,合并大多数的模型类,属性,CATEGORY
使用C++ Virtual 的虚函数
使用Swift 的结构体

为了缩短启动时间 可以采用的方法有
减少已有dylib的数量.

减少已有ObjC类的数量 以及删除静态初始化器

还有可用更多Swift语言加快速度 因为Swift真的很强大
Swift有全局变量 并且会被初始化 它们确保在使用前被初始化 但是其方法不是用初始化器 在后台 使用一次dispatch_once() 使用了一种调用点初始化器 所以转为Swift语言 将会做到这一点

最后 不鼓励使用dlopen() 它会带来细微的性能问题 很难诊断

使用Instruments 去检测启动时间


screenshot.png

dyld 的预绑定
我们使用预绑定技术 为系统中的所有dylib和你的程序 找到固定地址 动态加载器将会 加载这些地址的所有内容 如果成功 将会编辑 所有这些二进制数据 以获得所有预计算地址 然后下次 当它将所有数据放入相同地址时 不必进行任何其它额外的工作 这会大幅提高速度

但是这也意味着 每次启动时会编辑你的二进制数据 这并不是很好的做法 至少从安全性来说是如此

dyld2

dyld 2是dyld的 完全重写版本
正确支持C++初始化器语义, 扩展mach-o格式 并且更新dyld 从而获得高效率的C++库支持
它具有完整的本机dlopen 和dlsym实现 具有正确的语义 弃用了旧版API 这些旧版API仍然位于macOS中 没有加入到任何其它平台上
dyld的设计目标是提高速度

dyld3

image.png

dyld3的特点是进程外的且有缓存的,启动app前把很多耗时操作提前处理好了。据统计,在冷启动时,dyld3比dyld2快20%。

Dyld3分为out-of-process,和in-process。

out-process会做:

分析Mach-O Headers
分析以来的动态库
查找需要的Rebase和Bind的符号
将上面的分析结果写入缓存。

in-process会做:

读取缓存的分析结果
验证分析结果
加载Mach-O文件
Rebase&Bind
Initializers

dyld的东西比较深奥,建议大家再多去找找资料,dyld3核心就是在app启动之前就已经将二进制加入到缓存中,从而提升速度的.

这里差不多也看完了2017 session 的启动优化, 核心是dyld3的优化,能够在开发者这边操作的注意事项与2016 大多数也是通用的
1.减少动态库的依赖
2.减少指针的使用。(指针地址对齐的操作消耗时间)

  1. 优化Objc建立时间。这一步包含四个步骤:
    3.1注册类
    3.2更新类实例变量偏移(例如SDK更新)
    3.3注册Category
    3.4 选择器的唯一性

4: 初始化。在iOS平台下,如果项目使用Objc编写,尽量少使用+load方法,如果非要使用, 替换为+initialize,延迟加载。如果项目已经使用Swift编写,那就没什么优化的了,Apple暗地里帮我们调用了他们自己的initializer(dispatch_once), 确保Swift class不会被初始化多次。

关于优化第一帧

优化个人业务
在最小化工作时 应该推迟与 生成第一帧无关的任何内容
这意味着推迟 未显示的视图或尚未使用的 预加热功能等内容
还应该避免阻塞主线程 比如网络 I/O 文件 I/O 或其他
因为这会影响启动 将其移动到后台线程
应该注意 减少内存使用量分配和操作 内存可能需要时间 接下来 优先工作

使用Instrment 去检测UI

screenshot.png

如图所示,根据时间定位耗时的代码.

[图片上传中...(screenshot.png-85bb1a-1614424149540-0)]

本篇是自己看完wwdc的笔记式的内容.三篇session部分内容重复, 后面有时间再进行整理. 多谢观看

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容