抖音 Swift 编译优化 - 基于自定义 Toolchain 编译提速 60%

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

动手点关注

3aba04e9778eb2192f8657cd8f090376.gif

干货不迷路

本文重点探讨全部模块化后带来的依赖解析瓶颈,主要包括对头文件增量编译分析等内容。

优化方案基于 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 提供的头文件。

1b10a66a78fa7e54e8cc3b92279caf0b.png

如图,二者不可兼得,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%

可见该方案对编译速度的巨大提升。接下来就让我们回顾一下整个方案从预研到上线的过程。

方案原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值