如何查看编译时间
Optimization Level
设置xcode编译的线程数
Debug Information Format
将Build Active Architecture Only改为Yes
将Valid Architecture改为arm64,arm64e
二进制化
增量编译
分布式编译
其它
如何查看编译时间
终端内输入:
defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
然后你在编译的时候点击xcode顶部的那个进度条,当编译完成的时候就能查看编译时间。
Optimization Level
这个是xcode Built Setting里的一个参数,Optimization Level是指编译器的优化层度,优化后的代码效率比较高,但是可读性比较差,且编译时间更长。 它一共有以下几个选项:
- None: 编译器不会尝试优化代码,当你专注解决逻辑错误、编译速度快时使用此项。
- Fast: 编译器执行简单的优化来提高代码的性能,同时最大限度的减少编译时间,该选项在编译过程中会使用更多的内存。
- Faster: 编译器执行所有优化,增加编译时间,提高代码的性能
- Fastest: 编译器执行所有优化,改善代码的速度,但会增加代码长度,编译速度慢。
- Fastest, Smallest: 编译器执行所有优化,不会增加代码的长度,它是执行文件占用更少内存的首选方案
所以说我们平时开发的时候可以选择使用None来不给代码执行优化,这样既可以减少编译时间,又可以看出你代码哪里有性能问题。
而你的release版应该选择Fastest, Smalllest,这样既能执行所有的优化而不增加代码长度,又能使执行文件占用更少的内存。
pod里的Optimization Level
我们在使用pod的时候,每一个pod其实都是一个target,它有自己的Optimization Level。cocoapods默认给每一个pod的Optimization Level设置的是Fastest, Smallest,也就是说执行所有的优化和减少内存占用空间。
这样我们在开发的时候会有两个问题:一个是debug的时候无法输出pod源码里面的变量值,因为编译器已经给代码做了优化,它无法再记录你的变量值了。
还有一个就是编译时间长,拿我现在的工程来说,如果把所有pod的Optimization Level选项设置成None的话编译时间为2分30秒,如果为默认的Fastest, Smallest的话时间为3分15秒。
把所有pod的的Optimization Level设置为None只需在Podfile里加入以下代码即可(其中的"Dev"为你项目的Scheme):
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
if config.name.include?("Dev")
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
end
end
end
平均节省时间45秒,20%
设置xcode编译的线程数
defaults write xcodebuild PBXNumberOfParallelBuildSubtasks 8
defaults write xcodebuild IDEBuildOperationMaxNumberOfConcurrentCompileTasks 8
defaults write com.apple.xcode PBXNumberOfParallelBuildSubtasks 8
defaults write com.apple.xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks 8
XCode默认使用与CPU核数相同的线程来进行编译,但由于编译过程中的IO操作往往比CPU运算要多,因此适当的提升线程数可以在一定程度上加快编译速度。
平均节省时间15秒,8%
Debug Information Format
在工程对应Target的Build Settings中,找到Debug Information Format这一项,将Debug时的DWARF with dSYM file改为DWARF。
这一项设置的是是否将调试信息加入到可执行文件中,改为DWARF后,如果程序崩溃,将无法输出崩溃位置对应的函数堆栈,但由于Debug模式下可以在XCode中查看调试信息,所以改为DWARF影响并不大。这一项更改完之后,可以大幅提升编译速度。
其实Debug Information Format就是表示是否生成.dSYM文件,也就是符号表。如果为DWARF就表示不生成.dSYM文件。
This setting controls the format of debug information used by the developer tools. [DEBUG_INFORMATION_FORMAT]
DWARF - Object files and linked products will use DWARF as the debug information format. [dwarf]
DWARF with dSYM File - Object files and linked products will use DWARF as the debug information format, and Xcode will also produce a dSYM file containing the debug information from the individual object files (except that a dSYM file is not needed and will not be created for static library or object file products). [dwarf-with-dsym]
下面这句虽然能修改所有pod的Debug Information Format为DWARF,但是是没用的,主要还是看主工程里的Debug Information Format的设置。主工程如果为DWARF with dSYM file也会为pod里的代码生成符号表的。如上面的官方描述所说如果为.a的静态文件的话是不会生成符号表的。
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name == 'Dev'
config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf'
end
end
end
end
平均节省时间7秒,5%
将Valid Architecture改为arm64,arm64e
限制可能被支持的指令集的范围,也就是Xcode编译出来的二进制包类型最终从这些类型产生,而编译出哪种指令集的包,将由Architectures与Valid Architectures(因此这个不能为空)的交集来确定。
目前iOS移动设备指令集:
2018 A12芯片arm64e : iphone XS、 iphone XS Max、 iphoneXR
2017 A11芯片arm64: iPhone 8, iPhone 8 Plus, and iPhone X
2016 A10芯片arm64:iPhone 7 , 7 Plus, iPad (2018)
2015 A9芯片arm64: iPhone 6S , 6S Plus
2014 A8芯片arm64: iPhone 6 , iPhone 6 Plus
2013 A7芯片arm64: iPhone 5S
armv7s:iPhone5|iPhone5C|iPad4(iPad with Retina Display)
armv7:iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4
将Build Active Architecture Only改为Yes
这一项设置的是是否仅编译当前架构的版本,如果为No,会编译所有架构的版本。需要注意的是,此选项在Release模式下必须为No,否则发布的ipa在部分设备上将不能运行。这一项更改完之后,可以显著提高编译速度。
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name == 'Dev'
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
end
end
end
end
平均节省时间80秒,26%
二进制化
什么叫二进制化,其实就是把源码编译为静态库或动态库。也就是我们平常使用的.framework和.a文件,这些库都是已经编译好的,所以当你pod update或者pod install,就不用再重新编译一遍那么多文件了,能够显著减少编译时间。
pod-package
:可以将任意的 pod 打包成 Static Library,省去重复编译的时间,一定程度上可以加快编译时间
Carthage
增量编译
Buck
:是一套通用的构建系统,由 Facebook 开源。最大的特色是智能的增量编译可以极大地提高构建速度。最早听说 Buck 的时候,它还只能用在安卓上,现在已经适配了 iOS。
它能增快构建速度的主要原因是缓存了编译结果,通过持续监视项目目录的文件变化,每次编译时只编译有改动的文件。
Bazel 跟 Buck 很相似,是 Google 开源的,优缺点跟 Buck 都差不多,不再详细说了。
distcc 分布式编译
原理是把一部分需要编译的文件发送到服务器上,服务器编译完成后把编译产物传回来。我尝试了一下比较出名的 distcc,搭建过程比较简单,最后也能成功地把编译任务分派到内网的多台服务器上。但是其他编译服务器的 CPU 占用总是很低,只有 20% 左右;也就是说分派任务的速度甚至还赶不上服务器编译的速度,分派任务然后回传编译产物这个过程所耗费的时间超过了本地直接编译。不停调整参数反复试验了很多次,最后发现编译时间完全没有变快,甚至还有点变慢了。可能以我们目前项目的规模并不适合使用分布式编译。
其它方案
CCache是一个能够把编译的中间产物缓存起来的工具,而且比较稳定,因此可以打打提高编译速度。但是CCache不支持clang module,因此需要关闭项目中的Enable Modules,同时对于cocoapods管理的第三方库,也需要处理clang module的问题。具体使用方法可以参考文章:使用CCache让打包飞起来
参考:
http://www.cocoachina.com/articles/19665
https://www.zybuluo.com/qidiandasheng/note/587124
https://www.jianshu.com/p/c9e3fb3dfa53