iOS启动优化

希望总结项目中的启动优化,详细学习iOS启动流程

1. 想要对App进行启动优化需要优先了解App的启动时间,和个个启动过程中的时间占比(主要讲解Pre-main之前的过程)

  • Xcode 13.0 beta / iOS 15.0之前比较方便我们可以在 Xcode 中配置环境变量 DYLD_PRINT_STATISTICS 为 1(Edit Scheme → Run → Arguments → Environment Variables → +)。
截屏2023-07-22 22.18.59.png
  • Xcode 13.0 beta / iOS 15.0之后这个方法失效了苹果推荐我们使用instrument工具进行监测
截屏2023-07-22 22.20.51.png

2. 了解了方法后我们可以通过打印看到我们每个过程消耗的时间,此处有几个关键指标

  • dylib loading (动态库加载)

  • rebase/binding (偏移修正/符号绑定)

rebase(偏移修正):任何一个app生成的二进制文件,在二进制文件内部所有的方法、函数调用,都有一个地址,这个地址是在当前二进制文件中的偏移地址。一旦在运行时刻(即运行到内存中),每次系统都会随机分配一个ASLR(Address Space Layout Randomization,地址空间布局随机化)地址值(是一个安全机制,会分配一个随机的数值,插入在二进制文件的开头),例如,二进制文件中有一个 test方法,偏移值是0x0001,而随机分配的ASLR是0x1f00,如果想访问test方法,其内存地址(即真实地址)变为 ASLR+偏移值 = 运行时确定的内存地址(即0x1f00+0x0001 = 0x1f01)

  • Objc setup (Objc相关类的注册,selector唯一性检查)

dyld调用的objc_init方法,这个是runtime的初始化方法,在这个方法里面主要的操作就是加载类(对需要的class和category进行注册),objc_init方法通过内部的_dyld_objc_notify_register向dyld注册了一个通知事件,当有新的image(程序中对应实例可简称为image,如程序可执行文件macho,Framework,bundle等)加载到内存的时候,就会触发load_images方法,这个方法里面就是加载对应image里面的类,并调用load方法(在下一阶段initializer),如果有继承的类,那么会先调用父类的load方法,然后调用子类的,但是在load里面不能调用[super load]。最后才是调用category的load方法。总之,所有的load都会被调用到(注意:子类的initialize方法会覆盖父类,不同于load方法)

  • initializer (初始化执行load方法,创建静态全局变量等)

3. 介绍几个概念

1.Mach-O文件
Apple出品的操作系统的可执行文件格式几乎都是mach-o,iOS当然也不例外。
mach-o可以大致的分为三部分:

  • Header 头部,包含可以执行的CPU架构,比如x86,arm64
  • Load commands 加载命令,包含文件的组织架构和在虚拟内存中的布局方式
  • Data,数据,包含load commands中需要的各个段(segment)的数据,每一个Segment都得大小是Page的整数倍。
image.png

2.Virtual Memory
虚拟内存是建立在物理内存和进程之间的中间层。在iOS上,当内存不足的时候,会尝试释放那些只读的Page,因为只读的Page在下次被访问的时候,可以再从磁盘读取。如果没有可用内存,会通知在后台的App(也就是在这个时候收到了memory warning),如果在这之后仍然没有可用内存,则会杀死在后台的App。

  • 虚拟内存是在物理内存上建立的一个逻辑地址空间,它向上(应用)提供了一个连续的逻辑地址空间,向下隐藏了物理内存的细节。
  • 虚拟内存使得逻辑地址可以没有实际的物理地址,也可以让多个逻辑地址对应到一个物理地址。
  • 虚拟内存被划分为一个个大小相同的Page(64位系统上是16KB),提高管理和读写的效率。 Page又分为只读和读写的Page。

3.Page fault
在应用执行的时候,它被分配的逻辑地址空间都是可以访问的,当应用访问一个逻辑Page,而在对应的物理内存中并不存在的时候,这时候就发生了一次Page fault。当Page fault发生的时候,会中断当前的程序,在物理内存中寻找一个可用的Page,然后从磁盘中读取数据到物理内存,接着继续执行当前程序。

4.改善APP的启动

-在 dylib loading的过程中,会去装载app使用的动态库,而每一个动态库有它自己的依赖关系,所以会消耗时间去查找和读取,Apple官方建议尽量少的使用自定义的动态库,或者考虑合并多个动态库,其中一个建议是当大于6个的时候,则需要考虑合并它们。简单的举个例子比如使用cocoapods管理的多个自定义的UI组件可以合并成一个自己的UIKIT,同时也建议动态库转静态库

-减少+load的方法使用,+load方法中尽量少做耗时操作,+load中代码延迟到 main 之后子线程处理或者首页显示之后;改为 initialize 中执行,针对 initialize 中处理需要注意的是分类 initialize 会覆盖主类 initialize 以及有子类后 initialize 执行多次的问题,需要使用 dispatch_once 来保证代码只执行一次;

-二进制重排要实现符号的重排,一是需要我们收集整个启动链路上的方法和函数等符号,二是需要生成对应的 order 文件来配置 ld 中的 Order File 属性。当工程在编译的时候,Xcode 会读取这个 order 文件,在链接过程中会根据这个文件中的符号顺序来生成对应的 MachO。一般业界中收集符号的方案有两种:
1.Hook objc_msgSend,只能拿到 OC 以及 swift @objc dynamic 的符号;
2.Clang 插桩,能完美拿到 OC、C/C++、Swift、Block 的符号;
第二种方法实现成本较高
采用第一种方法在编译完成后通过验证 LinkMap 文件中 #Symbols: 部分符号顺序是否和 order 文件中的符号顺序一致来确定是否配置成功即可

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

推荐阅读更多精彩内容