Xcode编译疾如风-2.并行编译
Xcode 编译是一个需要 CPU 运算以及大量 IO 操作的过程。我们将编译任务分配给多个 CPU 来提高单位时间内的编译速度。
线程
Xcode 默认使用与 CPU 核数相同的线程来进行编译,但由于编译过程中的 IO 操作通常比 CPU 运算要多,适当提升线程数可以在一定程度上加快编译速度。
代码语言:javascript复制defaults write com.apple.dt.xcodebuild PBXNumberOfParallelBuildSubtasks `sysctl -n hw.ncpu`
defaults write com.apple.dt.xcodebuild IDEBuildOperationMaxNumberOfConcurrentCompileTasks `sysctl -n hw.ncpu`
defaults write com.apple.dt.Xcode PBXNumberOfParallelBuildSubtasks `sysctl -n hw.ncpu`
defaults write com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks `sysctl -n hw.ncpu`
sysctl -n hw.ncpu
执行后会获取到电脑的 CPU 核心数,PBXNumberOfParallelBuildSubtasks
和IDEBuildOperationMaxNumberOfConcurrentCompileTasks
则控制着并行构建任务使用的线程数,我们可以适当提高线程数来编译加速。
一般经验是对于 CPU 密集型任务,假设 CPU 核数为 N,则线程池数设置为核数 N 1,因为 CPU 密集型任务使得 CPU 使用率很高,如果开过多的线程数,会大大增加上下文切换的次数,反而会带来额外的开销。对于 IO 密集型任务,线程池设置为 2N,IO 密集型任务 CPU 使用率并不高,因此可以让 CPU 在等待 IO 的时候去处理别的任务,这样能够充分利用 CPU 时间。小菜的电脑是 8 核,尝试着将线程数设置为了 16,经过测试,小菜的 M1 电脑全量编译提升了大概 20s 左右。
并行编译 Parallelize Build
在 Xcode 的 scheme 设置中,Xcode会默认勾选 ☑️ Parallelize Build。
该选项允许 Xcode 编译时分析各个构建任务的彼此依赖情况,然后并行构建。
我们来看看 WWDC2018 session 415_behind_the_scenes_of_the_xcode_build_process
。
项目中的源代码,包括头文件、C、C 、Objective-C、Swift等文件,经过构建系统 LLVM 以及 Swift 编译器处理后,生成最终的app。
Session 中以 PetWall app 作为示例,这是个用来展示宠物图片的简单应用。
在整个生成 PetWall.app 过程中,我们要编译源代码、Storyboard、xcassets、链接,运行自定义 shell 脚本,代码签名等。这里面会涉及到大量的构建任务,依赖关系十分复杂,而构建系统的用处,就是将任务的执行部署自动化。
那么构建任务的执行顺序怎么决定?取决于任务的依赖关系。以编译任务为例, 它需要输入源代码文件,比如 PetController.m,然后输出目标文件 PetController.o。同样,链接器任务,需要由编译器在上个任务中生成的目标文件再生成可执行或 lib 文件,比如 PetWall 可执行文件,最终会存到 .app 资源文件包。
构建系统通过依赖关系,决定任务执行的顺序,以及并行运行的任务。构建系统的第一步就是要获取构建描述,根据 Xcode 项目文件配置,分析依赖关系,最终生成一个有向图,图中描述了项目中的输入和输出文件,以及处理它们的执行任务。
开启并行编译的好处不言而喻。我们在优化编译时长的时候,首先要确认这个选项是否开启。
有些项目比较老,可能没有开启,那么不妨开启下。如果出现了编译报错等问题,往往是任务的依赖出现了问题。常见的解决方式是在Build Phases
中的Dependencies
中设置好依赖项,妥善解决好依赖问题应该就能解决报错问题。
阿姆达尔定律
思考下,并行编译是银弹吗?非也。
阿姆达尔定律是一个估算通过多核并行能够获得多少性能提升的经验法则。内容是:
通过并行计算所获得的系统性能提升效果,会随着无法并行的部分而产生饱和。
可并行化部分占比 P 为 90% 时,无论如何提高并行程度(提高N),整体上最多获得的性能提升无法超过基准的 10 倍。(1-P)部分表示无法并行的部分,这部分便是瓶颈。
并行这部分就到这,下节小菜会从工程配置上阐述配置对编译速度的影响。
等我。
更多阅读
- WWDC2018 Session415[1]
- https://gist.github.com/nlutsenko/ee245fbd239087d22137[2]
参考资料
[1]
WWDC2018 Session415: https://developer.apple.com/videos/play/wwdc2018/415/
[2]
https://gist.github.com/nlutsenko/ee245fbd239087d22137: https://gist.github.com/nlutsenko/ee245fbd239087d22137