分析Swift项目的编译时间

本文翻译自:Profiling your Swift compilation times

我遇到一个问题。我正在开发的一个全新的应用-是100%用Swift来写的。考虑到这个项目只有大概200个文件,我注意到它需要的编译时间超过了我的想象,更重要的是,它比前几个星期的编译速度慢了很多。在这个问题变得越来越糟糕之前,我需要尽快找到问题的根源。

第一步是添加 -Xfrontend -debug-time-function-bodies 这个Swift 编译选项:

这会让这个编译器输出一个函数编译的时长(感谢 Kevin Ballard 给我这个线索)。这个编译日志可以在Xcode 的 Report 窗口中看到,但需要你手动一个个展开每个文件:

下一步为了理解它们,需要把所有这些日志聚合在一个文件。

我们使用 xcodebuild 命令工具来把所有的日志输出到控制台:

# Clean and build, capturing only lines containing `X.Yms` where X > 0, sorting from largest to smallest
xcodebuild -workspace App.xcworkspace -scheme App clean build | grep [1-9].[0-9]ms | sort -nr > culprits.txt

接下来就是在这些输出中找到我想要的信息。我发现有超过1200行的数据是编译超过3秒的,谢天谢地的是这么多行都是三个相同的函数重复很多次(我对编译器不是很懂,不明白为什么会出现这种情况,但是输出的数据中包含了“closure”闭包这个关键词还是提供了一些线索)

3158.2ms	/Users/Bryan/Projects/App/FileA.swift:23:14	@objc get {}
3157.8ms	/Users/Bryan/Projects/App/FileA.swift:23:52	(closure)
3142.1ms	/Users/Bryan/Projects/App/FileA.swift:23:14	@objc get {}
3141.6ms	/Users/Bryan/Projects/App/FileA.swift:23:52	(closure)
3139.2ms	/Users/Bryan/Projects/App/FileA.swift:23:14	@objc get {}
3138.7ms	/Users/Bryan/Projects/App/FileA.swift:23:52	(closure)
3128.3ms	/Users/Bryan/Projects/App/FileB.swift:27:22	final get {}
3109.9ms	/Users/Bryan/Projects/App/FileA.swift:23:52	(closure)
3052.7ms	/Users/Bryan/Projects/App/FileA.swift:23:14	@objc get {}
3052.6ms	/Users/Bryan/Projects/App/FileA.swift:23:14	@objc get {}
3052.2ms	/Users/Bryan/Projects/App/FileA.swift:23:52	(closure)
3052.1ms	/Users/Bryan/Projects/App/FileA.swift:23:52	(closure)
3049.0ms	/Users/Bryan/Projects/App/FileB.swift:27:22	final get {}
3026.1ms	/Users/Bryan/Projects/App/FileB.swift:27:22	final get {}

更疯狂的是,所有这三个函数都是一行简单的代码。重写这三行代码就可以让我的项目编译时间快60%。我知道这很多人不爽,但是老实说,我非常高兴弄清楚了究竟是什么原因,如果下次遇到同样的问题,我知道自己该怎么做了。

你可能想知道这个三行代码是什么。这三行代码都非常相似,类似下面的:

return [CustomType()] + array.map(CustomType.init) + [CustomType()]

我不能确定造成这个问题是因为数组的 append 操作,或者mapping 操作,还是两者的结合。我放弃使用这些函数,不理会是否影响性能,添加了额外的临时变量和可变参数,用普通的方式改写。我不是第一个发现这个数组添加的操作很慢,就因为这样一行优雅,看似无害的代码让我亲身经历了这个痛苦。

Swift 仍然是一个非常年轻的语言,有这样的问题很正常,作为一个开放的社区,我们应该互相帮助,防止另一个痛苦发生。

最近的文章

Jenkins 编译包含Watch OS2 App Target的应用时报错

错误重现我们使用Jenkins 来进行我们的代码集成编译,当应用内添加了 Watch OS2 App的支持时,提交上去的代码会编译失败。失败提示如下:找不到 Watch App。错误分析我们发现其实是编译出来了,只是路径没有找对。分析我们的编译脚本:xcodebuild -scheme ${SCHEME_NAME} -workspace test.workspace -configuration ${CONFIGURATION_MODE} clean build CONFIGURATION...…

iOS继续阅读
更早的文章

iOS Keyboard Extension 开发过程遇到的坑

功能按键使用图片每个键盘都需要有一个按钮,那就是切换“下一个键盘”的按钮。在系统键盘,这个按钮使用了一个Emoji表情中的 🌐表情来显示。但是对于其它的功能按键,却没有对应的Unicode编码,因此在字体库中也找不到对应的图形,而且Unicode 中的这个图形集合的展示是不统一的: 🌐⇪⌫⌨? 。所以最好还是叫UE重新设计一下这些功能按键的图片吧。当然,你也可以自己绘制这个按钮了。可以参考这个开源项目。tasty-imitation-keyboard,这个开源项目里面的所有Functio...…

iOS继续阅读