为什么Swift编译时间如此之慢?
我使用的是Xcode 6 Beta 6 这件事困扰了我一段时间,但现在已经到了几乎无法使用的地步 我的项目开始有65个Swift文件和一些桥接的Objective-C文件(这并不是问题的原因) 似乎对任何Swift文件的任何轻微修改(如在应用程序中很少使用的类中添加一个简单的空格)都会导致重新编译指定目标的整个Swift文件 在深入调查之后,我发现占用编译器几乎100%时间的是为什么Swift编译时间如此之慢?,swift,optimization,compilation,type-inference,compilation-time,Swift,Optimization,Compilation,Type Inference,Compilation Time,我使用的是Xcode 6 Beta 6 这件事困扰了我一段时间,但现在已经到了几乎无法使用的地步 我的项目开始有65个Swift文件和一些桥接的Objective-C文件(这并不是问题的原因) 似乎对任何Swift文件的任何轻微修改(如在应用程序中很少使用的类中添加一个简单的空格)都会导致重新编译指定目标的整个Swift文件 在深入调查之后,我发现占用编译器几乎100%时间的是CompileSwift阶段,在该阶段中,Xcode对目标的所有Swift文件运行swiftc命令 我做了一些进一步的调
CompileSwift
阶段,在该阶段中,Xcode对目标的所有Swift文件运行swiftc
命令
我做了一些进一步的调查,如果我只保留带有默认控制器的app委托,编译速度非常快,但是随着我添加越来越多的项目文件,编译时间开始变得非常慢
现在只有65个源文件,每次编译大约需要8/10秒。一点也不快
除此之外,我没有看到任何帖子讨论这个问题,但它是Xcode 6的旧版本。所以我想知道我是不是唯一一个这样的人
更新
我在和上检查了一些Swift项目,但没有一个项目有足够的Swift文件进行实际比较。我发现唯一一个启动的项目有一个合适的大小,即使它只有十几个源文件,我仍然能够验证同样的东西,一个简单的空间和整个项目需要重新编译,这开始需要一点时间(2/3秒)
与Objective-C代码相比,analyzer和编译速度都非常快,这让人感觉Swift永远无法处理大型项目,但请告诉我我错了
使用Xcode 6 Beta 7更新
仍然没有任何改善。这开始变得可笑了。由于Swift中缺少#import
,我真的不知道苹果如何能够优化这一点
使用Xcode 6.3和Swift 1.2更新
苹果增加了(以及许多其他编译器优化)。您必须将代码迁移到Swift 1.2才能看到这些好处,但苹果在Xcode 6.3中添加了一个工具来帮助您做到这一点:
但是
不要像我那样高兴得太快。他们用来使构建增量化的图形解算器还没有得到很好的优化
事实上,首先,它不会查看函数签名的更改,因此如果在一个方法的块中添加空格,则依赖于该类的所有文件都将重新编译
其次,它似乎是基于重新编译的文件创建树,即使更改不会影响这些文件。例如,如果将这三个类移动到不同的文件中
class FileA: NSObject {
var foo:String?
}
class FileB: NSObject {
var bar:FileA?
}
class FileC: NSObject {
var baz:FileB?
}
现在,如果修改FileA
,编译器显然会将FileA
标记为要重新编译。它还将重新编译FileB
(根据对FileA
的更改可以,但是FileC
也会重新编译,因为FileB
是重新编译的,这非常糟糕,因为FileC
在这里从不使用FileA
所以我希望他们改进依赖树解算器。。。我已经用这个示例代码打开了一个
使用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代码,这是不错的,但并不出色。它经历了第2次和第3次快速迁移。在2014年年中的Macbook pro(2.5 GHz Intel Core i7)上编译大约需要5/6百万美元,在干净的版本上也可以
然而,尽管苹果声称:
当仅发生小的更改时,Xcode不会重建整个目标。(28892475)
显然,我认为我们中的许多人在检查完这些废话后只是笑了(将一个私有(private!)属性添加到我的项目的任何文件将重新编译整个内容…)
我想在苹果开发者论坛上向大家介绍一些关于这个问题的更多信息(同时感谢苹果开发者偶尔就这个问题进行交流)
基本上,人们已经想出了一些方法来尝试改进增量构建:
标题\u映射\u使用\u VFS
项目设置设置为true
查找隐式依赖项
let pipeResult =
seq |> filter~~ { $0 % 2 == 0 }
|> sorted~~ { $1 < $0 }
|> map~~ { $0.description }
|> joinedWithCommas
var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
"url" : self.url?.absoluteString ?? "",
"title" : self.title ?? ""
])
return dic.copy() as NSDictionary
var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
"url" : self.url?.absoluteString ?? "",
"title" : NSString(string: self.title ?? "")
])
return dic.copy() as NSDictionary
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
.....
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
....
var a = ["a": "b",
"c": "d",
"e": "f",
"g": "h",
"i": "j",
"k": "l",
"m": "n",
"o": "p",
"q": "r",
"s": "t",
"u": "v",
"x": "z"]
var a = NSMutableDictionary()
a["a"] = "b"
a["c"] = "d"
... and so on
abs(some_optional_variable ?? 0)
abs((some_optional_variable ?? 0) as VARIABLE_TYPE)
...
✓ Compile EntityObserver.swift (1623 ms)
✓ Compile Session.swift (1526 ms)
✓ Compile SearchComposer.swift (1556 ms)
...
xcodebuild -workspace App.xcworkspace -scheme App clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > culprits.txt
// Build time: 5238.3ms
return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22, height: bounds.height)
// Build time: 32.4ms
var padding: CGFloat = 22
if let rightView = rightView {
padding += rightView.bounds.width
}
if let leftView = leftView {
padding += leftView.bounds.width
}
return CGSizeMake(size.width + padding, bounds.height)
SWIFT_WHOLE_MODULE_OPTIMIZATION = YES
let sum = [1,2,3].map({String($0)}).flatMap({Float($0)}).reduce(0, combine: +)
let numbers: [Int] = [1,2,3]
let strings: [String] = sum.map({String($0)})
let floats: [Float] = strings.flatMap({Float($0)})
let sum: Float = floats.reduce(0, combine: +)
1.0 + (1.0 + (1 * (1.0 + 1.0))) // 3429ms
1.0 + (1.0 + (1.0 * (1.0 + 1.0))) // 5ms