猿问

为什么Swift编译时间这么慢?

我正在使用Xcode 6 Beta 6。


这已经困扰了我一段时间,但是现在已经到了几乎无法使用的地步。


我的项目已经开始有一个体面的65个斯威夫特文件的大小和几个桥接Objective-C的文件(这是真的不是问题的原因)。


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


经过更深入的研究后,我发现CompileSwiftXcode在swiftc目标的所有Swift文件上运行命令的阶段占了编译器时间的几乎100%。


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


现在只有65个源文件,每次编译大约需要8/10秒。一点也不快。


我还没有看到任何帖子谈到这个问题,除了这一个,但所以我想知道如果我在这种情况下,只有一个,这是一个旧版本的Xcode 6。


我已经在GitHub上检查了一些Swift项目,例如Alamofire,Euler和CryptoSwift,但是它们都没有足够的Swift文件可以进行实际比较。我发现唯一一个启动时大小合适的项目是SwiftHN,即使它只有十几个源文件,我仍然能够验证同一件事,一个简单的空间,整个项目需要重新编译,这开始需要一个很少的时间(2/3秒)。

与分析器和编译都快速发展的Objective-C代码相比,这确实让Swift永远无法处理大型项目,但是请告诉我我错了。

Xcode 6 Beta 7更新

仍然没有任何改善。这开始变得荒谬。由于缺少#importSwift,我真的看不到苹果将如何进行优化。

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

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

现在,如果您进行修改FileA,则编译器显然会标记FileA为要重新编译。它还将重新编译FileB(根据对的更改,这将是可以的FileA),而且还FileC因为FileB重新编译了,这很糟糕,因为在此FileC从未使用FileA过。

因此,我希望他们能改进依赖关系树求解器...我已经用此示例代码打开了雷达。

Xcode 7 beta 5和Swift 2.0更新

昨天,Apple发布了Beta 5,在发布说明中我们可以看到:

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

我已经尝试过了,我必须说它现在真的(真的!)运行良好。他们迅速优化了增量构建。

我烈建议您创建一个swift2.0分支,并使用XCode 7 beta 5使代码保持最新。您会对编译器的增强功能感到满意(但是我会说XCode 7的全局状态仍然很慢且有错误)。


Xcode 8.2更新


自从我最近一次更新此问题以来已经有一段时间了。


现在,我们的应用程序大约有2万行代码,几乎都是Swift代码,虽然不错,但并不出色。它经历了迅速的2迁移,而不是迅速的3迁移。在2014年中的Macbook pro(2.5 GHz Intel Core i7)上进行编译大约需要5 / 6m,这在干净的版本上还可以。


但是,尽管苹果声称:增量构建仍然是一个笑话:


仅发生很小的更改时,Xcode不会重建整个目标。(28892475)


显然,我认为我们很多人在检查了这个废话之后就笑了(向我项目的任何文件添加一个私有(私有!)属性都会重新编译整个过程……)


我想指出你们在Apple开发人员论坛上的这个线程,该线程上有关于此问题的更多信息(以及不时地对此事的Apple开发人员的交流)


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


将HEADER_MAP_USES_VFS项目设置添加到true

禁用Find implicit dependencies您的方案

创建一个新项目,然后将文件层次结构移至新项目。

我将尝试解决方案3,但解决方案1/2不适用于我们。


具有讽刺意味的是,在整个情况下,有趣的是,当我们遇到第一个编译缓慢问题时,尽管我们从Apple那里获得了实际的改进,但在第一篇文章中,我们使用的是Xcode 6和Swift 1或Swift 1.1代码。这种情况与Xcode 6一样糟糕。


实际上,我真的很后悔为我们的项目选择Swift而不是Obj / C,因为它每天都会令人沮丧。(我什至改用AppCode,但这是另一个故事)


无论如何,截至撰写本文时,我看到这则SO帖子具有32k +的视图和143个ups,所以我想我不是唯一的一个。尽管对这种情况感到悲观,但还是呆在那儿,隧道尽头可能有些亮光。


猛跑小猪
浏览 979回答 3
3回答

交互式爱情

如果您试图确定特定的文件来减慢编译时间,则可以尝试通过xctool在命令行中对其进行编译,这将使您逐文件进行编译。需要注意的是,默认情况下,每个CPU内核同时构建2个文件,不会为您提供“净”使用时间,而是给您绝对的“用户”时间。这样,所有时间在并行化文件之间变得均匀,并且看起来非常相似。为了克服这个问题,请将-jobs标志设置为1,这样它就不会并行化文件构建。这将花费更长的时间,但最终您将获得“净”编译时间,可以按文件进行比较。这是一个应做的技巧示例命令:xctool -workspace <your_workspace> -scheme <your_scheme> -jobs 1 build“编译Swift文件”阶段的输出类似于:...&nbsp; &nbsp;✓ Compile EntityObserver.swift (1623 ms)&nbsp; &nbsp;✓ Compile Session.swift (1526 ms)&nbsp; &nbsp;✓ Compile SearchComposer.swift (1556 ms)...从此输出中,您可以快速确定哪些文件比其他文件花费的时间更长。此外,您可以高精度确定重构(显式强制转换,类型提示等)是否正在降低特定文件的编译时间。注意:从技术上讲,您也可以这样做,xcodebuild但是输出的内容非常冗长且难以使用。
随时随地看视频慕课网APP
我要回答