动手点关注

干货不迷路
本文重点探讨全部模块化后带来的依赖解析瓶颈,主要包括对头文件增量编译分析等内容。
优化方案基于 Swift Toolchain 源码,本文不再探讨 Toolchain 相关基本概念及配置流程等,仅聚焦方案本身。
背景
随着混编落地的业务场景越来越多,越来越大,开发中出现的性能痛点开始显现,问题很明显集中在被 Swift 环境所依赖的 OC 仓的头文件改动上。因此基建架构把重点放在接口层依赖的性能分析上,力求解决性能瓶颈。
抖音基础技术团队借助自定义 Toolchain 能力,通过自定义编译参数,裁剪 Clang Header 指定内容,最终实现编译提速 60% 。
本方案已于 2022 年 11 月底上线,在抖音稳定运行近 5 个月。下面就让我们一起回顾下整个方案从提出到落地的全过程。
初步分析
在混编场景下,若要确保 OC 与 Swift 间尽可能充分地互操作,则模块化的启用无法仅用在 Swift 编译上下文中——Swift编译导出的 Clang Header,在工程中以$(project_name)-Swift.h形式出现,将其需要被 re-export 引用的 OC 依赖项,以模块的形式导出,这就意味着若 OC 编译不启用模块化,则无法正确使用 Swift 提供的头文件。

如图,二者不可兼得,Objc Pod D 为了能够解析语句@import A;而引入A.modulemap,则其与 A 的互操作不可能再基于文本导入的逻辑,而全面转向模块化。
对于抖音而言,巨型 OC 项目的大量头文件传递依赖的历史包袱,使得在 OC 编译中引入模块化是一场灾难。模块化环境下,缓存系统决议是否要命中 .o 缓存的耗时,比文本环境下重新编译耗时还要长;增量编译时,也会导致广泛的模块重编,改动一个头文件,就要等待数分钟。
传递依赖治理是一项长期工程,但编译优化等不了那么久,我们需要一个可以快速解决的方案。
优化效果
在介绍方案之前,先上结论。
在抖音工程中选取代码量最大的 OC&Swift 混编仓库进行测试:
OC 增量编译:选取被 Swift 依赖的 OC 接口层头文件进行改动,编译耗时降低 60%
Swift 增量编译:选取被 OC 依赖的 Swift public class 进行改动,编译耗时相近,无变化
全量编译:清除本地编译缓存进行 clean build,编译耗时降低 17%
可见该方案对编译速度的巨大提升。接下来就让我们回顾一下整个方案从预研到上线的过程。

本文介绍了在Swift与Objective-C混编项目中遇到的编译性能瓶颈,特别是当OC头文件改动时。通过自定义SwiftToolchain,裁剪ClangHeader的内容,实现了编译速度提升60%,并在实际工程中取得了显著效果。文章详细阐述了优化方案的原理、预研过程、开发调试步骤以及上线后的验证,展示了通过定制工具链进行编译优化的可能性。
最低0.47元/天 解锁文章
2万+

被折叠的 条评论
为什么被折叠?



