当前位置:   article > 正文

iOS app的启动优化_ios instruments 启动分析

ios instruments 启动分析

返回上级目录:iOS面试专题一

1.冷启动分为两个阶段:main函数之前和之后

iOS pre-main 打印时间 超过100%

iOS App冷启动优化 - 知乎

2.pre-main阶段

Pre-main阶段,当用户点击App冷启动,系统会做好准备工作,剩余的工作由DYLD动态链接器完成,称为pre-main。在iOS15/macOS12以前,可以通过添加run启动参数arguments DYLD_PRINT_STATISTICS打印启动时间,以后要靠自己的工具类或者timeProfile
Pre-main工作:
1.设置运行环境/环境变量
2.加载共享缓存// iOS特性,从iOS3.1开始,会把系统的动态库抽取出来,如UIKIT,WEBKIT,大大减小app消耗内存
3.实例化主程序
4.加载需要的动态库,根据DYLD_INSERT_LIBRARIES判断
5.链接主程序,rebase()因为从iOS4.3开始使用了ASLR,需要重新定位主程序,bind()对程序二进制和符号表进行绑定
6.链接插入的动态库
7.弱符号绑定
8执行初始化方法,执行所有load方法,这是可以优化的地方
9.查找入口点,执行并返回
请添加图片描述
请添加图片描述

2.1 Load dylibs image:加载动态库

  • 动态链接器dyld

针对这一步的优化:减少非系统库的依赖

2.2 Rebase/Bind image:指针重定位

  • ASLR(address space layout randomization): 地址空间布局随机化
  • 镜像(Mirroring): 是一种文件存储形式,是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像

针对这一步的优化:减少Objc类数量,减少selector数量

2.3 Objc setup:Objc类初始化

这阶段做的事情

  • 读取二进制文件的DATA段的内容,找到与objc相关的信息
  • 注册Objc类
  • 确保selector的唯一性
  • 读取protocol以及category的信息

2.4 initializers:各种初始化

+load和+initialize的区别

请添加图片描述
iOS initialize方法及与load的区别

load_images

  • 调用Objc的load方法

针对这一步的优化:懒加载
使用+initialize来代替+load

pre-main阶段具体优化

  • 2.+load方法处理

  • 3.针对减少不必要的库

  • 4.合并功能类似的类和扩展(Category)

  • 5.压缩资源图片

3.main()函数之后

  • swift中不能重写load和initialize方法
    请添加图片描述

mach-O是苹果系统的可执行文件。一般静态库会被集成到主程序的mach-O之中,动态库会被拷贝到BUndle里的framework文件夹中,一般在启动的时候加载,说到启动,就不得不提启动优化了

我的另外的相关博客:
iOS swift中的main函数
iOS 性能优化(一):Improving Your App‘s Performance

4.二进制重排

我的二进制重排部分都是对这篇博客的理解:iOS App启动优化(三):二进制重排

4.1 什么是二进制重排

请添加图片描述

内存是分页管理的,映射表不能以字节为单位,是以页为单位

  • Linux以4K为一页
  • macOS以4K为一页
  • iOS以16K为一页
  • 在mac终端输入pageSize会得到4096(1024*4),如下图:
    请添加图片描述

Page Fault 缺页中断

  • 当app需要使用某一块虚拟内存的地址时,会通过地址映射表(虚拟内存->物理内存)查询该虚拟地址是否已经在物理内存中申请了空间
  • 如果已经申请了则通过表的记录访问物理内存地址
  • 如果没有申请则申请一块物理内存空间并记录在表中
  • 当数据没有在物理内存会进行下列操作:1.系统阻塞改该进程。2.将磁盘中对应Page的数据加载到内存。3.把虚拟内存指向物理内存。这三个行为就是Page Fault
  • 系统在分配物理内存给当前进程的时候遵循以下原则:1.如果有空闲内存空间就放空的内存空间中。2.如果没有就覆盖其他进程的数据。3.具体覆盖由操作系统处理

什么是二进制重排:

  • 虚拟内存技术会产生缺页中断(Page Fault),这个过程是个耗时操作
  • 每页耗时也有很大差距,1微妙到0.8毫秒不等。
  • 使用过程中对这点耗时感觉不明显,但是启动时加载大量数据,如果产生大量缺页中断(Page Fault),时间叠加后用户会有明显感知。
  • 如果我们把所有启动时候的代码都放在一页或者两页,这样就很大程度减少了启动时的缺页中断(Page Fault)从而优化启动速度,这就是二进制重排

4.2 怎样进行二进制重排

二进制重排的中心思想是重新排列方法符号的顺序,使启动的相关方法排在最前面从而减少启动Page Fault的数量

1.用Instrument查看缺页中断的次数
Instruments -> system trace -> target -> 项目名 -> Main Thread -> Virtual Memory -> File Backed Page In
请添加图片描述
如下图,也可以直接搜索main,找到main thread
请添加图片描述
请添加图片描述

2.Link Map File: 可以看到原来符号方法的排列(Target -> Build Setting -> 搜索Write Link Map File)

  • 二进制重排
    二进制重排就是要重新排列这些方法符合的顺序,中心思想就是把启动用到的代码挪到前面的位置加载

3.order_file: 重新编写符号排列的顺序

  • Xcode提供了排列符号的设置给开发者,设置order_file即可。苹果也一直身体力行,objc源码就采用了二进制重排优化
  • 设置order_file:Target -> Build Setting -> Linking -> Order File 设置 order file 的路径
    编写order_file,下图是本人亲自测试的截图:
  • 重排前的link map file:
    请添加图片描述
    link.order文件:
    请添加图片描述
    重排后的link map file:
    请添加图片描述

5.LLVM,编译期插桩,获取方法符号

  • 我们要跟踪到每个方法的执行,从而获取到启动时方法执行的顺序,然后再按照这个顺序去编写order file
  • 跟踪的具体实现会用到clang(轻量级编译器,LLVM的前端部分)的SanitizerCoverage(代码覆盖率检测工具),通过看守者跟踪(Tracing PCs with guards)
    iOS App启动优化(六):实用党直接看这里

参考博客:
iOS 性能优化:优化 App 启动速度 - CSDN

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/291771
推荐阅读
相关标签
  

闽ICP备14008679号