赞
踩
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.查找入口点,执行并返回
针对这一步的优化:减少非系统库的依赖
针对这一步的优化:减少Objc类数量,减少selector数量
这阶段做的事情
- 读取二进制文件的DATA段的内容,找到与objc相关的信息
- 注册Objc类
- 确保selector的唯一性
- 读取protocol以及category的信息
load_images
- 调用Objc的load方法
针对这一步的优化:懒加载
使用+initialize来代替+load
- 1.删除无用代码(未被调用的静态变量,类和方法)
AppCode使用介绍
2.+load方法处理
3.针对减少不必要的库
4.合并功能类似的类和扩展(Category)
5.压缩资源图片
- swift中不能重写load和initialize方法
mach-O是苹果系统的可执行文件。一般静态库会被集成到主程序的mach-O之中,动态库会被拷贝到BUndle里的framework文件夹中,一般在启动的时候加载,说到启动,就不得不提启动优化了
我的另外的相关博客:
iOS swift中的main函数
iOS 性能优化(一):Improving Your App‘s Performance
我的二进制重排部分都是对这篇博客的理解:iOS App启动优化(三):二进制重排
内存是分页管理的,映射表不能以字节为单位,是以页为单位
- 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)从而优化启动速度,这就是二进制重排
二进制重排的中心思想是重新排列方法符号的顺序,使启动的相关方法排在最前面从而减少启动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:
- LLVM 命名最早源自于底层虚拟机(Low Level Virtual Machine)的缩写
- iOS LLVM及编译过程
- 我们要跟踪到每个方法的执行,从而获取到启动时方法执行的顺序,然后再按照这个顺序去编写order file
- 跟踪的具体实现会用到clang(轻量级编译器,LLVM的前端部分)的SanitizerCoverage(代码覆盖率检测工具),通过看守者跟踪(Tracing PCs with guards)
iOS App启动优化(六):实用党直接看这里
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。