iOS进阶:编译速度优化
编译耗时的检查
Swift的表达式和函数的编译时长检查
在
build setting
的Other Swift Flags
中设置:1
2
3
4// 编译耗时超过 100ms 的函数或表达式给出警告
-Xfrontend -warn-long-function-bodies=100
-Xfrontend -warn-long-expression-type-checking=100查看总耗时
在终端执行如下命令,重启Xcode,编译后可以看到总耗时:
1
defaults write com.apple.dt.Xcode ShowBuildOperationDuration -bool YES
编译优化怎么做
针对OC的优化——重点在于减少无效的引用
pch
文件:删除使用不多的引用.h
文件:减少.h
文件中的引用,将.h
中导入改为声明#import
改为@class
针对Swift的优化——重点在于减少类型检查
明确变量类型
闭包:
- 避免闭包的嵌套——因为swift推断闭包方法需要把内部所有代码都推断完才能推断出闭包的类型
- 避免使用闭包来初始化属性
lazy
变量:减少lazy
变量的使用,或将lazy
变量声明改为函数调用形式不推荐写法:
1
2
3
4
5
6private(set) lazy var chartViewColors: [UIColor] = [
UIColor.red,
UIColor.blue,
UIColor.green,
UIColor.purple,
]推荐写法:
1
2
3
4
5
6
7
8
9
10private(set) lazy var chartViewColors: [UIColor] = createChartViewColors()
private func createChartViewColors() -> [UIColor] {
return [
UIColor.red,
UIColor.blue,
UIColor.green,
UIColor.purple,
]
}集合类型:明确集合类型,避免使用
+
合并两个集合三元运算符——
?:
:使用if...else...
代替nil
的聚合运算——??
:使用条件绑定来解决一行表达式不要做太多事情,比如既做判断又做计算
其他
- 项目设置:使用
New Xcode Build System
- DSYM:将
Debug Information Format
改为DWARF
,设置在Debug下不生成DSYM,只在Release下生成 - 模块化:将pod第三方库打包成
.a
文件,减少编译时间;缺点是不方便调试
编译器层面优化
WMO(Whole-Module Optimization)简介
WMO即全模块优化。在编译项目时,会将同属于一个 Module(可以理解为一个 Target、一个 Package)的所有源代码都串起来,进行整体的一个分析与优化,区别于 Single-File Optimization(单文件优化,简称 SFO)。WMO 可以更好的统筹全局,去 inline 函数调用、排除死函数(即写了却从不调用的函数)等等,使编译速度加快。但是,WMO 只是在 Release 模式下成为了默认且推荐的选项,在 Debug 模式下默认依然是 None。
怎样利用WMO优化编译速度
Uber 的开发团队偶然发现如果把所有 Model 文件全部合并到一个文件去编译, 那编译时间会从 1min 35s 减少到 17s, 那么我们如果把所有代码文件都合并到一起, 那就可以极大地优化编译速度了。
WHO(Whole-Module-Optimization) 也会把文件合并起来再进行编译, 实际使用时我们发现编译虽然快了, 但对于编译时间的减少还是远没有直接把文件合并到一起那么有效。
主要原因是因为 WMO 除了合并文件之外, 还会在预编译阶段做一些优化,来方便编译器将方法的调用优化为静态调用或者内联进去:
- 检测没有被调用的方法和类型, 在预编译期去掉它们;
- 给没有被继承的类, 没有被继承的方法加上
final
标签。
这些优化会对于程序的效率有很大的提升, 但编译时间会有所增加。
最终发现,通过增加一个编译宏就可以做到只合并文件, 而不做优化:
设置 -> Build Setting
-> Add User-Defined Settings
, 设置key 为 SWIFT_WHOLE_MODULE_OPTIMIZATION
, value 设为 YES, 然后把优化级别设为 None,这样就可以实现Debug模式下的编译耗时的优化。