快手 iOS 编译速度优化
如果无法正常显示,请先停止浏览器的去广告插件。
1. 快手 iOS 编译速度优化
崔通
快手 • 客户端 • 基础架构负责人
2.
3. 崔通
快手 • 客户端 • 基础架构
基础组件
App架构
编译构建
4. 研发效能满意度(NPS)调查结果
30%
0.3
来自开发同学的吐槽
0.2
0.2
14%
14%
0.1
0
“验证一个问题,打包就等45分钟”
-0.1
“点了编译按钮,然后可以打局游戏”
-0.2
“服务打包能不能快点,真XX慢”
-0.2
-21%
-27%
-0.3
客户端构建
5. 问题在哪里?
基础架构同学
V.S
业务开发同学
构
结
程
工
化
简
,
工程再复杂,我只改动了两个文件
工程复杂,代码多,所以编译速度变慢
物
产
译
缓存编
6. 快手编译构建优化之路
快手主站工程Pods和代码增⻓趋势
如何解决源码编译慢的问题?
600
如何保证构建工具快速迭代?
450
300
如何解决CI打包慢、排队时间⻓?
150
如何进一步提高缓存复用?
0
2019年1月
2019年7月
2020月1月
2020月7月
Pod数
2021月1月
2021月6月
代码行数(万行)
7. 01
快手二进制化实践
「解决」每次只能源码编译
8. 本地编译慢的原因 (2018)
工程结构
Podfile
全部业务代码集中在主Target下
Podfile中只有一些三方库
源码编译
pod “AFNetworking” , 3.2.1
pod “SDWebImage” , 5.8.3
…
~ 30 mins
9. 工程Pod化 & 二进制化
改造前
本地Pod
整理模块
批量创建podspec
忽略dependency
二进制化
合码后自动构建
无版本号概念
无需手动发布
10. 工程Pod化 & 二进制化
快手自研构建工具:高达
原始 Podfile 内容
构建时 Podfile 内容
源码和二进制切换
white_list = [‘gifHomeModule’]
代码改动,自动回落成源码
require ‘scripts/gundam.rb’
prepare_gundam
require ‘scripts/gundam.rb’
prepare_gundam
pod “gifLiveModule”,
:path => ‘<source-code/path>’
pod “gifPostModule”,
:path => ‘<source-code/path>’ pod “gifLiveModule”,
:path => ‘<downloaded-binary/path>’
pod “gifPostModule”,
:path => ‘<downloaded-binary/path>’
pod “AFNetworking”, “3.2.1” pod “AFNetworking”,
:path => ‘<downloaded-binary/path>’
11. 二进制组件包的生产和消费
生产
消费
本地缓存
触发任务
12. Pod二进制化效果
构建速度大幅度提高
~ 30 ~ 5
min min
遇到的新问题
如何解决源码编译慢的问题?
如何保证构建工具快速迭代?
如何解决CI打包慢、排队时间⻓?
“构建脚本越来越难维护啦”
如何进一步提高缓存复用?
13. 02
构建脚本工程化
「解决」构建工具自身可以持续快速迭代
14. v1.0版本遇到的问题 (2019)
v1.0
7 files
v1.3.1
CocoaPods升级困难 升级后有大量编译错误,工具无法正常工作
需求增多 Podfile 越写越复杂
缺少数据度量 优化没有数据支撑
15. CocoaPods 1.7 Released! (2019)
From
v1.7 带来新特性
CDN 源
多Xcodeproj
增量 pod install
To
16. 痛苦的升级过程
问题一:File not Found
#import “PDDebugger.h”
#import <PonyDebugger/PDDebugger.h>
错误数爆表! (999)
17. 痛苦的升级过程
问题二:podspec 普遍没有声明依赖
依赖关系计算
接管Header Search Path
脚本修改 xcconfig
18. 脚本工具工程化
v1.0 v2.0
Now
7 46 400+
ruby files ruby files ruby files
高达v2.0
标准Ruby Gem
尽量少的hook
19. 分层架构
自更新 & 集成测试
满足自定义需求
100% UT覆盖
20. 插件设计
40+ 自定义插件
无用AB下线 Treat Warnings as Errors
开启LinkMap 路由自动收集头文件
本地Git Hook Flutter 本地开发模式
重启并自动编译 架构依赖检查
组件包调试
……
21. 插件设计
Pod install 之后操作
执行Apple script
40+ 自定义插件
无用AB下线 Treat Warnings as Errors
开启LinkMap 路由自动收集头文件
本地Git Hook Flutter 本地开发模式
重启并自动编译 架构依赖检查
组件包调试
……
22. 构建工具配合架构升级
提供架构依赖关系防劣化检查
底层不依赖上层
业务之间无相互依赖
X
X
X
X
23. 关于数据度量
2
3 整体大盘数据
4 个体详细数据
$ pod install —verbose
1 $ pod install
24. 关于数据度量
5
单文件编译耗时分析
发现PCH优化点 提速50%
25. 构建工具工程化效果
独立Gem,服务于快手主站外其他App
CocoaPods 最新版本
满足多元的业务需求
通过数据监控,发现瓶颈问题并优化
源码编译速度提升 50%
如何解决源码编译慢的问题?
如何保证构建工具快速迭代?
如何解决CI打包慢、排队时间⻓?
遇到的新问题
“打包太慢啦”
如何进一步提高缓存复用?
26. 03
分布式打包 & 硬件升级
「解决」CI出包慢、封板日排队久
27. 打包平台体验差 (2020)
代码量↑ 打包量↑
↑24.15% ↑465%
打包体验↓
打包 慢
排队 久
2020年春节后打包需求激增
28. 打包平台排队的原因
单机器构建
打包时间与代码量线性相关
有重复构建,造成浪费
pod install
“班⻋”模型,发版日流量高峰
link
29. 从单机器到打包集群
pod install
Checkout branch
pod install
pods
1
20s
2
5 ~ 10 mins
3
单架构 6 mins
30. 机器调度与复用
派发中心:选择“空闲”机器
2
3
A
1
A
B
C
B
Bucket1
(0 ~ 15s left)
D
C
D
Scheduler
Dispatcher
Bucket2
(15 ~ 30s left)
2
2
A
B
F
E
1
E
F
A
B
调度中心:历史打包数据
Bucket3
(30 ~ 45s left)
31. 提审包提高优先级
Test Task 1
A
B
D
C
Test Task 2
A
B
E
Scheduler
F
A B E
C D F
A B D
Dispatcher
C
RB Task 1
E
A B
E F
C
F
D
任务优先队列,确保关键打包任务资源充足
32. 硬件升级 - M1
M1带来编译速度提升 20 ~ 30%
90
67.5
88.8
85.5
61.2
59.2
48.5
44.4
45
40.5
30.1
稳定性问题 22.5
Jenkins 0
gifLiveModule
gifVideoProcessModule
gifPostCommon
32
27
gifFeedBaseModule
普通mini
gifUserProfileModule
M1 mini
33. 分布式+硬件升级优化效果
如何解决源码编译慢的问题?
打包平台测试包
30 16 11
min min min
如何保证构建工具快速迭代?
M1
如何解决CI打包慢、排队时间⻓?
AppStore包
150 50 40
min min min
M1
如何进一步提高缓存复用?
34. 分布式+硬件升级优化效果
如何解决源码编译慢的问题?
遇到的新问题
“Pod快爆炸啦”
如何保证构建工具快速迭代?
如何解决CI打包慢、排队时间⻓?
如何进一步提高缓存复用?
35. 04
动态库复用
「解决」如何进一步提高缓存复用
36. 工程复杂度越来越高
卡,且容易崩溃!
37. 工程复杂度越来越高
600
Pod数量爆炸
450
pod install 慢
300
二进制组件包下载 慢
IDE响应 慢
150
Link时间 ⻓
0
2019年1月
2019年7月
2020月1月
2020月7月
Pod数
2021月1月
2021月6月
代码行数(万行)
38. 快手动态库结构
HomeFramework
BaseFramework
PostFramework
LiveFramework
SocialFramework
LazyBaseFramework
Extensions
CommonFramework
Today
Share
…
39. 快手动态库结构
30+
Pods
HomeFramework
def home_framework_pods
pod “gifHomeModule”, :path => ‘<path>’
pod “gifPlayerAdapter”, :path => ‘<path>’
…
end
def base_framework_pods
pod “AFNetworking”, “3.2.1”
pod “SDWebImage”, “5.8.3”
…
end
300+
Pods
BaseFramework
PostFramework
LiveFramework
SocialFramework
LazyBaseFramework
Extensions
CommonFramework
Today
Share
…
40. 动态库缓存复用
1
Pod
HomeFramework
def home_framework_pods
pod “gifHomeFramework”, :path => ‘<path>’
end
def base_framework_pods
pod “gifBaseFramework”, :path => ‘<path>’
end
PostFramework
LiveFramework
SocialFramework
1
Pod
BaseFramework
LazyBaseFramework
Extensions
CommonFramework
Today
Share
…
41. 动态库缓存复用
HomeFramework
BaseFramework
PostFramework
LiveFramework
SocialFramework
LazyBaseFramework
Extensions
CommonFramework
< 20 Pods
Today
Share
…
42. 还有什么可以复用?
Assets.car
50 ~ 60 s
8000+资源文件
直接 copy 缓存的 Assets.car
install_resource “<downloaded-cache-path>”
+
+
43. 动态库复用效果
如何解决源码编译慢的问题?
Pod install
220 80 60
second second second
如何保证构建工具快速迭代?
M1
Clean build
如何解决CI打包慢、排队时间⻓?
200 35 20
second second second
M1
如何进一步提高缓存复用?
44. 动态库复用效果
如何解决源码编译慢的问题?
如何保证构建工具快速迭代?
如何解决CI打包慢、排队时间⻓?
< 3 mins 出一个测试包
如何进一步提高缓存复用?
45. 快手iOS编译构建优化之路
4
3
2
1
动态库复用 & 资源复用
分布式构建 & 硬件升级
构建工具工程化 & 数据建设
工程Pod化 & 二进制化
46. 双端策略一致
编译加速
Android
源码module
动态aar
Parallel
Transform
Host APP
字节码工具
动态插件化
全源码工程
Post Plugin/App
Social Plugin/App
iOS
源码Pod
二进制Pod
分布式
资源处理
动态库复用
Feed Plugin/App
Live Plugin/App
远程编译集群
劣化预警系统
实时数据
智能答疑
文档检索
智能问题分析
依赖分析
构建诊断
数据看板
构建Bot
开发者工具
常用工具
47. 千人移动研发团队编译构建新趋势
极致速度 & 智能服务
48. 扫码了解-快手大前端技术号
49.
50.