Arclin

Advocate Technology. Enjoy Technology.

0%

Xcode 14 优化

本文简述Xcode 14 的编译优化

Link fast: Improve build and launch time

什么是链接

链接过程

如图所示,链接将不同的语言,通过前端编译器,编译为中间代码LLVM IR,然后再通过,然后再通过LLVM后端编译器,编译成对应处理器架构的机器语言。

通过这张图我们可以清晰地看到有了中间代码IR的存在,我们就可以在开发高级语言的时候不用去考虑不同处理器之间的细节,而是统一由LLVM去处理,大大降低了开发成本。

然后链接这一行为,是发生在LLVM后端编译器上的,因为我们平时写代码的时候,以OC语言为例,每个m代码文件都会被编译成o文件,那多个o文件之间的互相调用,要怎么做呢,这时候就是通过链接把他们都合并成一个文件。比如在iOS中,最后就是产出一个Mach-o文件。

也就是说,链接将各个模块(各个文件的编译产物)的函数连接起来,产出各个架构的可执行文件。

然后在iOS中,链接方式有两种

  • 静态链接(ld64):影响app的编译时间和包大小,选择性加载
  • 动态链接(dyld):影响App的启动耗时

在iOS中我们制作的一些.a或者.framework这些静态库最后就会经过静态链接过程链接到我们的可执行文件中。

动态链接一般就是链接一些系统库,在启动的时候按需,动态地加载。

Mach-0文件

mach-o_format_basic_structure.png

首先贴下官方的文档介绍

一个Mach-O主要包括三个区域

  • Header
    • 文件类型,目标架构类型等(比如可执行文件、静态库、arm64构架等)
  • Load commands
    • 描述文件在虚拟内存中的逻辑结构、布局(数据段,代码段…都有哪些段,顺序如何,分别是做什么的,怎么做,由Load commands来描述)
    • 包含着多种命令,包括代码签名命令,符号表命令等
  • Raw segment data
    • Load command中定义的Segment的原始数据(在Load command中定义的那些段的原始具体数据)

ld64 优化点

对于大部分项目来说,速度提升近2倍

利用多核能力和优化算法加速链接

  • 与时俱进:利用多核能力,并行计算UUID和签名散列值,类似zld
    • 在以往的链接中,一个方法被调用之后,如果里面依赖着另外一个方法,那么链接器就回去找依赖的方法在哪儿,然后找到之后就继续找依赖的方法所依赖的另一个方法,是一串连续的操作。而上面这些操作都是单核串行执行的。Xcode 14优化之后将会利用硬件多核的能力去并行的查找,提高效率。
  • 算法调优:字符串表示(C++ string_view objects)升级
  • 硬件加速:升级加密库
  • 配置升级:优化链接配置参数

静态链接参数 需要开启all_load 才可以使用上述说明的使用多核能力提升链接速度

静态链接参数说明

  • all_load:适用于加载静态库的大部分方法或函数
    • 开了了all_load之后,链接器会无差别地把.a或者.framework里面的方法和函数链接起来,不同于以前的选择性加载:发现这个方法会被调用时再去取。
    • 可以加快链接速度,可以并行解析加载
    • 缺点:包体积变大,线上环境不建议开启。
  • dead_strip:链接器删除不可访问的代码和数据,配合all_load
    • 因为all_load会无差别地链接所有方法和函数,导致了包体变大,所以这里开启dead_strip可以删除无用的方法和函数
    • 注意这里有个风险点:通过runtime调用的方法是检测不到的,所以有可能会被裁掉,编译不会报错,运行时找不到符号才报错。线上环境不建议开启。
  • no_exported_symbols:不导出符号文件,节省时间很短,不考虑
    • 线上不能开启,因为我们需要用到符号表去排查问题
  • no_deduplicate:减少重复符号检查来提高链接速度,选择已加载的第一个符号
    • 不建议开启,相同的符号可能实现方法会不一样

Xcode配置

dlyd 优化点

编译过程中,不需要将主项目中对动态库中的接口的调用,链接到主项目中,而是在主项目中,留下了类似协议的调用,直到启动App,才将真正的实现,关联起来—也就是dlyd过程

举个例子就是编译链接的时候留一个占位符,表示自己需要这么一个函数,等到启动的时候,系统再从动态库去查找这个符号。

  • 优势:链接耗时
  • 劣势:启动耗时,并且因为不同Data pages导致的缺页中断更加凸显

优化

  • dylib chainede fixups(13.4)动态库链式修复:即本身动态库里面方法和函数的地址和app需要用到的地址是不一样的,所以需要动态修复地址,但是需要将部署最低版本设到13.4以上,这样子启动时的动态库加载过程才会得到加速

  • page-in linking:针对DATA端的符号,内核提前加载

pre-main 注意事项

  1. 禁止做I/O和网络操作
  2. 任何超过毫秒级别的操作都不应该放到这

Xcode 14 新增链接相关命令行工具

  • dyld_usage:获取dyld正在做什么,应用在macos-app或者iOS模拟器

  • dyld_info:检查磁盘上和当前dyld缓存中的二进制文件