最近网上闲逛,发现这篇文章挺好的。翻译一下 以后备用
1 函数和表达式的类型检查
swift编译速度缓慢大部分是因为类型检查耗时长。默认情况下Xcode不会显示编译慢的代码。你可以通过指令来显示编译慢的函数和表达式,
添加如下指定到build settings
-> Other Swift Flag
-
-Xfrontend -warn-long-function-bodies=100
(100
这里意思100ms,修改这个值主要根据你电脑和项目的速度) -Xfrontend -warn-long-expression-type-checking=100
编译运行,可以看到如下结果
下一步就是对应John Sundell 和
Robert Gummesson 文章 去优化编译器提示的问题代码。
提示:这个功能在启动模块优化的情况下无法工作,所以请关闭模块优化Whole Module Optimization
📖Sources:
- Guarding Against Long Compiles
- Measuring Swift compile times in Xcode 9 · Jesse Squires
- Improving Swift compile times — Swift by Sundell
- Swift build time optimizations — Part 2
编译缓慢的文件
上面描述如何知道函数和表达式的编译时间,不过去知道文件的编译速度也是很有意思的。
但是 Xcode 没有响应操作的UI界面,因此你可以可以通过CLI来编译项目
xcodebuild -destination 'platform=iOS Simulator,name=iPhone 8' \
-sdk iphonesimulator -project YourProject.xcodeproj \
-scheme YourScheme -configuration Debug \
clean build \
OTHER_SWIFT_FLAGS="-driver-time-compilation \
-Xfrontend -debug-time-function-bodies \
-Xfrontend -debug-time-compilation" | \
tee profile.log
如果你使用 workspace 请使用-workspace YourProject.xcworkspace
去替换 -project YourProject.xcodeproj
然后使用如下代码来提取一些有趣的统计数据:
awk '/Driver Compilation Time/,/Total$/ { print }' profile.log | \
grep compile | \
cut -c 55- | \
sed -e 's/^ *//;s/ (.*%) compile / /;s/ [^ ]*Bridging-Header.h$//' | \
sed -e "s|$(pwd)/||" | \
sort -rn | \
tee slowest.log
你最终得到一个slowest.log
文件,其中包括项目中的文件以及他们的编译时间。类似
2.7288 ( 0.3%) {compile: Account.o <= Account.swift }
2.7221 ( 0.3%) {compile: MessageTag.o <= MessageTag.swift }
2.7089 ( 0.3%) {compile: EdgeShadowLayer.o <= EdgeShadowLayer.swift }
2.4605 ( 0.3%) {compile: SlideInPresentationAnimator.o <= SlideInPresentationAnimator.swift }
提示: 和上面的提示一样
📖Sources:
只构建一个活跃的架构 (Build active architecture only)
这个设置是默认的,不过你要检查一下是否设置正确。如下:
📖Sources:
dSYM生成
默认新的项目中,所有的build不会生成sSYM文件。不过有时候当我们运行在一个去分析崩溃的而且不能断点调试的真机上,这是相当有用的。(确实 要点个赞 这个tip)
推荐设置:
📖Sources:
整个模块优化
另外一些平常的技巧:
在debug配置中改变
Optimization Level
为Fast, Whole Module Optimization
-
只在debug配置下为
Other Swift Flags
添加-Onone
标记
它指示编译器器做了如下操作:
- 一个模块里的所有源文件都运行在一个编译任务中,而不是一个原本件对应一个编译任务。
- 减少了并行性,但也减少了重复的工作
- 这是更快的bug; 但我们需要稍作重复的工作。改进它是以后的目标
注意的是在这设置下可能有的小改变增量构建中显的有点更缓慢。不过在最坏的情况下你会看到巨大的提速(项目中有很多2x)
📖Sources:
- Developear - Speeding Up Compile Times of Swift Projects
- Slava Pestov on Twitter: “@iamkevb It runs one compiler job with all source files in a module instead of one job per source file”
针对Coco'apod做整个模块优化
如果你使用Cocoapod,你应该考虑在你的pod项目没有优化的情况下启用WNO,你可以在你的Podfile
文件中添加如下post_install
钩子
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name == 'Debug'
config.build_settings['OTHER_SWIFT_FLAGS'] = ['$(inherited)', '-Onone']
config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Owholemodule'
end
end
end
end
然后运行pod install
. 确保在此更改前后比较构建时间,以确认有改进。
三方依赖
这里有2种方式去在你的项目中嵌入三方依赖
- 作为那种你每次clean就要重新操作的原件(例如Cocoapod,git submodules,复制粘贴的代码,app target 依赖的子项目的内部库)
- 作为一个与构建的 framework/library(例如 Carthage ,第三方不想提供源代码发布的静态库)
CocoaPods 是专为iOS 设计最流行的依赖管理,但是导致很长的编译时间。作为第三方库的源代码,在大多数情况下。每次clean都要重新编译。通常情况下,你不需要这样做。但是实际上,确实有必要这么做(如 分支切换 Xcode bug)
尽管Carthage非常难用,但是如果你在乎构建时间的话,这是一个好的选择。仅仅当你更改依赖列表时候(添加删除依赖,升级版本)才构建外部依赖库。这需要可能5或者15分钟,但是比起嵌入代码到Cocoapod你要少做很多。
📖 Sources:
- time spent waiting for Xcode to finish builds 😅
模块化
swift的增量编译并不完美。有一些项目,我们改变一个字符串导致整个增量构建过程中重新编译。它可以被调试和改变。但很多好的工具不能被使用。
为了避免这样的问题,你需要将你的项目划分到不同的模块中。在iOS 中动态库和静态库都可以(Xcode9 swift支持静态库)
让我们假如你的项目依赖一个叫DatabaseKit
的内部framework。这种方法保证当你项目更改一些内容重新编译的时候。DatabaseKit
在增量构建中不会重新编译。
📖Sources:
XIBs
xib/sb vs 纯代码 这是一个非常热门的话题。不过我们不会在这里充分讨论。有趣的是,当你修改IB中的内容,这有这个文件被编译。另一方面,如果你修改UIView子类的一个公共方法swift编译器会决定重新编译大部分项目。
📖Sources:
Xcode Schemes
通常项目设置有3个targets
- App
- AppTests
- AppUITests
在一个scheme中处理是很好的但是我们可以做的更好。我们最近的设置是由3个scheme组成。
APP
使用cmd - b上构建应用程序的时候只运行单元测试。用于短迭代,例如在UI代码中,只需要构建所需的代码。
App - Unit Test Flow
当构建app 和 单元测试的时候,只运行单元测试。在编写单元测试的时候非常有用。因为当你构建单元测试的时候能立刻发现错误,而不用运行他们。
App - All Tests Flow
构建app 和所有的测试的时候。运行所有的测试。UI测试的时候非常有用。
📖Sources:
使用新的Xcode构建系统
Xcode9 苹果介绍了一种新的构建系统。目前是预览版,默认不使用。这笔默认构建系统明显更快。在Xcode文件菜单中选择Workspace or Project Settings 去可以切换都新的构建系统。
📖Sources:
显示Xcode的编译时间
最后,为了让我们知道我们的构建系统是否提升了。我们需要在Xcode界面上显示构建时间。运行如下命令显示:
$ defaults write com.apple.dt.Xcode ShowBuildOperationDuration -bool YES
一旦我们这样做了。cmd b我们可以看见
我推荐比较相同条件下的构建时间
1 退出Xcode
2 清除派生的数据
3 在Xcode项目中打开你的项目
4 在Xcode打开或索引阶段完成后立即开始构建。第一个方法似乎更具有代表性,因为从Xcode 9构建开始也执行了索引。
可选择的,你可以在命令行下运行
$ time xcodebuild other params
📖Sources: