为什么Swift的编译时间如此缓慢?

221

我正在使用 Xcode 6 Beta 6。

这是一件困扰我已经有一段时间的事情,但现在已经到了几乎无法使用的程度。

我的项目开始拥有 65 个 Swift 文件和一些桥接的 Objective-C 文件(它们并不是问题的原因)。

似乎对任何一个 Swift 文件进行轻微修改(例如在应用程序中几乎不使用的类中添加一个简单的空格)都会导致为指定目标重新编译整个 Swift 文件。

经过深入调查,我发现几乎占用了 100% 编译器时间的是 CompileSwift 阶段,Xcode 在您的目标的所有 Swift 文件上运行 swiftc 命令。

我进行了进一步调查,如果我只保留带有默认控制器的应用程序委托,则编译非常快。但随着我添加越来越多的项目文件,编译时间开始变得非常缓慢。

现在仅有 65 个源文件,每次编译需要大约 8/10 秒钟。根本不够“swift”。

除了 这个 之外,我没有看到任何讨论此问题的帖子,但那是旧版本的 Xcode 6。所以我想知道是否只有我处于这种情况。

更新

我检查了一些在GitHub上的 Swift 项目,例如AlamofireEulerCryptoSwift,但它们中没有一个拥有足够的 Swift 文件来进行比较。我找到的唯一一个开始变得“不错”的项目是SwiftHN,即使它只有十几个源文件,我仍然能够验证相同的情况,一个简单的空格整个项目都需要重新编译,这开始需要一点时间(2/3 秒钟)。

与 Objective-C 代码相比,分析器和编译都快得惊人,这真的感觉像是 Swift 永远无法处理大型项目,但请告诉我我错了。

使用 Xcode 6 Beta 7 更新

仍然没有任何改进。这开始变得荒谬了。由于 Swift 中缺少 #import,我真的看不出 Apple 如何能够进行优化。

使用Xcode 6.3和Swift 1.2更新

苹果公司增加了增量编译(以及许多其他编译器优化)。您需要将代码迁移到Swift 1.2才能看到这些好处,但是苹果在Xcode 6.3中添加了一个工具来帮助您完成此操作:

Enter image description here

然而

不要像我一样太快高兴。他们用于使构建增量的图形求解器尚未优化得很好。

首先,它不会查看函数签名更改,因此,如果您在一个方法的块中添加空格,则所有依赖于该类的文件都将重新编译。

其次,它似乎基于重新编译的文件创建树,即使更改不影响它们。例如,如果您将这三个类移动到不同的文件中:

class FileA: NSObject {
    var foo:String?
}
class FileB: NSObject {
    var bar:FileA?
}
class FileC: NSObject {
    var baz:FileB?
}
如果你修改了FileA,编译器会显然标记FileA需要重新编译。它还会重新编译FileB(根据对FileA的更改是可以接受的),但因为FileB被重新编译了,所以它也会重新编译FileC,这很糟糕,因为FileC从未在此处使用FileA

因此,我希望他们能改进这个依赖树求解器... 我用这个示例代码打开了一个radar

更新:使用Xcode 7 beta 5和Swift 2.0

昨天,苹果发布了beta 5版,并在发布说明中看到:

Swift语言和编译器
• 增量构建:仅更改函数主体不应再导致重建依赖文件。(15352929)

我试了一下,必须说现在它的工作效果非常好。他们在Swift中大大优化了增量构建。

我强烈建议您创建一个swift2.0分支,并使用XCode 7 beta 5保持代码更新。你会喜欢编译器的增强功能(不过我要说,XCode 7的全局状态仍然很慢和有缺陷)。

更新:使用Xcode 8.2

距离上次关于这个问题的更新已经有一段时间了,现在是时候更新一下了。
我们的应用程序现在有大约20k行几乎完全是Swift代码,这还算不错但也不是最出色的。它经历了swift 2和swift 3迁移。在干净的构建上,在中2014年Macbook pro(2.5 GHz英特尔Core i7)上编译大约需要5/6分钟。

但是即使苹果声称:

Xcode不会在发生小更改时重新构建整个目标。(28892475)

显然,当我们检查这个无聊的东西(向项目的任何文件添加一个私有属性(私有)!)后,我们都笑了...

我想指出一下Apple开发者论坛上的这个帖子,其中有一些关于此问题的更多信息(以及偶尔得到的赞赏的苹果开发者交流)。

基本上,人们想出了一些方法来尝试改善增量构建:

  1. 添加项目设置HEADER_MAP_USES_VFS并将其设置为true
  2. 从您的方案中禁用查找隐式依赖项
  3. 创建一个新项目并将文件层次结构移动到新项目中。

我将尝试解决方案3,但解决方案1/2对我们没有起作用。

在整个情况中真正具有讽刺意味的是,当我们遇到第一次编译缓慢的问题时,看着这个问题的第一篇帖子时,我们正在使用Xcode 6和我相信是Swift 1或Swift 1.1代码,现在大约两年过去了,尽管Apple有了实际改进,但情况与Xcode 6时一样糟糕。多么具有讽刺意味啊。

我真的非常后悔选择Swift而不是Obj / C来进行我们的项目,因为它带来了每日的挫败感。(我甚至转到了AppCode,但那是另一回事)

无论如何,我发现这个SO帖子在本文撰写时已经有32k+的浏览量和143个upvotes,所以我想我不是唯一一个遇到这种情况的人。坚持下去,尽管对这种情况感到悲观,但可能会有一些曙光。

如果您有时间(和勇气!),我想Apple欢迎有关此事的报告。

更新Xcode 9

今天偶然发现this。 Xcode悄悄引入了一个新的构建系统,以改善当前可怕的性能。您必须通过工作区设置启用它。

enter image description here

已经尝试过了,但在完成后将更新此帖子。看起来很有前途。


2
我曾经遇到过类似的问题,最终发现是因为实体类中使用了自定义运算符来从JSON反序列化。如果你也在使用这种方式,请尝试逐个将其转换为普通函数,并观察是否有任何变化。 - Antonio
4
自从 XCode 6 beta 6 以来,我的项目编译速度变得非常慢,让我感到非常焦虑。我不确定是因为 beta 版本的更改还是因为我的代码问题。尽管我的项目还没有变得很大(约有 40-50 个 Swift 文件)。 - BadmintonCat
2
随着我的项目规模的增长,编译变得无法忍受地缓慢。我还依赖于几个Pods,这肯定会加剧问题。这是使用最近的非beta版本。 - Andy
2
增量构建仍然采用“保守的依赖分析”,因此您可能仍会看到比绝对必要更多的文件重新构建。希望随着时间的推移会有所改善。 - nmdias
1
@ZigDanis 绝对不行,只有当XCode 7达到GM状态后,您才能提交应用程序到iTunes Connect。但是,您应该尽可能保持swift2更新。我注意到我的结尾短语很令人困惑,我已经更新了它以使其更清晰。 - apouche
显示剩余15条评论
22个回答

0

Xcode 6.3.1对我来说一无是处 - 当我添加了大约100个Swift文件时,Xcode会在构建和/或索引过程中随机挂起。我尝试了模块化选项,但没有成功。

安装和使用Xcode 6.4 Beta实际上对我有用。


0

这对我来说就像魔法一样有效 - 加速Swift编译。它将编译时间从10分钟缩短到3分钟。

它说你应该在添加其他Swift标志时打开整个模块优化并添加-Onone

我正在使用Xcode 8.3/Xcode 8.2上的Swift 3


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接