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

为什么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命令 我做了一些进一步的调

我使用的是Xcode 6 Beta 6

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

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

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

在深入调查之后,我发现占用编译器几乎100%时间的是
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
  • 从方案中禁用
    查找隐式依赖项
  • 创建新项目并将文件层次结构移动到新项目
  • 我将尝试解决方案3,但解决方案1/2对我们不起作用

    在这种情况下,具有讽刺意味的是,看看关于这个问题的第一篇文章,我们在第一次编译时使用的是Xcode 6,我相信是swift 1或swift 1.1代码,现在大约两年后,尽管苹果公司做出了实际改进,但情况和Xcode 6一样糟糕。真讽刺

    事实上,我非常后悔选择Swift而不是Obj/C作为我们的项目,因为它每天都会带来挫折。(我甚至切换到AppCode,但这是一个错误。)
    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