为什么Swift的编译时间这么慢? [英] Why is Swift compile time so slow?

查看:331
本文介绍了为什么Swift的编译时间这么慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是Xcode 6 Beta 6.



这是一段时间以来一直在欺骗我一段时间,但它达到了一个点,现在勉强可用。



我的项目开始有一个体面的大小为65的Swift文件和一些桥接的Objective-C文件的问题)。



似乎任何轻微的修改任何Swift文件(如在一个类中添加一个简单的白色空间,在应用程序中几乎不使用)将导致



经过更深入的调查,我发现几乎100%的编译器时间是 CompileSwift 阶段,其中Xcode对目标的所有Swift文件运行 swiftc 命令。



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



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



我没有看到任何关于此问题的帖子,除了。



UPDATE With Xcode 7 beta 5 and Swift 2.0



昨天苹果发布了beta 5,我们可以看到:


Swift语言&编译器
•增量构建:只改变函数的主体不应再导致依赖文件被重建。 (15352929)


我已经试过了,我必须说它是真的(真的!他们大大优化了swift中的增量构建。



我强烈建议您创建一个 swift2.0 分支,并使用XCode 7 beta 5保持您的代码更新。

解决方案

div>

好吧,事实证明,Rob Napier是对的。它是一个单一的文件(实际上是一种方法),导致编译器去berzek。



现在不要误会我。 Swift每次都会重新编译所有文件,但是现在的伟大之处在于,Apple对其编译的文件添加了实时编译反馈,因此Xcode 6 GM现在可以显示正在编译的Swift文件以及实时编译的状态您可以在此屏幕截图中看到:





因此,这很方便地知道哪些文件需要这么长时间。在我的case是这段代码:

  var dic = super.json()。mutableCopy()as NSMutableDictionary 
dic.addEntriesFromDictionary([
url:self.url?.absoluteString ??,
title:self.title ??
])

return dic.copy()as NSDictionary

因为属性 title 的类型为 var title:String?,而不是 NSString 。编译器在将它添加到 NSMutableDictionary 时会疯狂。



将其更改为:

  var dic = super.json()。mutableCopy()as NSMutableDictionary 
dic.addEntriesFromDictionary([
url:self .url?.absoluteString ??,
title:NSString(string:self.title ??)
])

return dic.copy as NSDictionary

使编译从10/15秒(甚至更多)下降到一秒...惊人。


I'm using Xcode 6 Beta 6.

This is something that's been bugging me for some time now, but it's reaching a point where it's barely usable now.

My project is starting to have a decent size of 65 Swift files and a few bridged Objective-C files (which are really not the cause of the problem).

It seems like any slight modification to any Swift file (like adding a simple white space in a class that's barely used in the app) will cause the entire Swift files for the specified target to be recompiled.

After a deeper investigation, I've found that what is taking pretty much 100% of the compiler time is the CompileSwift phase where Xcode runs the swiftc command on all Swift files of your target.

I did some further investigation, and if I only keep the app delegate with a default controller the compilation is very fast, but as I was adding more and more of my project files, the compile time was starting to get really slow.

Now with only 65 source files, it takes about 8/10 seconds to compile each time. Not very swift at all.

I haven't seen any post talking about this issue except this one, but it was an old version of Xcode 6. So I'm wondering if I'm the only one in that case.

UPDATE

I've checked a few Swift projects on GitHub like Alamofire, Euler and CryptoSwift, but none of them had enough Swift files to actually compare. The only project I found that was starting a have decent size was SwiftHN, and even though it only had a dozen source files I was still able to verify the same thing, one simple space and the whole project needed recompilation which was starting to take a little time (2/3 seconds).

Compared to Objective-C code where both analyzer and compilation are blazing fast, this really feels like Swift will never be able to handle big projects, but please tell me I'm wrong.

UPDATE With Xcode 6 Beta 7

Still no improvement whatsoever. This is starting to get ridiculous. With the lack of #import in Swift, I really don't see how Apple will ever be able to optimize this.

UPDATE With Xcode 6.3 and Swift 1.2

FINALLY

Apple has added incremental builds (and many other compiler optimizations). You have to migrate your code to Swift 1.2 to see those benefits, but Apple added a tool in Xcode 6.3 to help you do so:

HOWEVER

Don't rejoice too quickly as I did. The graph solver that they use to make the build incremental is not very well optimised yet.

Indeed first, it doesn't look at function signature changes so if you add a space in the block of one method, all files depending on that class will be recompiled.

Second, it seems to create the tree based on the files that were recompiled even if a change doesn't affect them. For example, if you move these three classes into different files

class FileA: NSObject {
    var foo:String?
}
class FileB: NSObject {
    var bar:FileA?
}
class FileC: NSObject {
    var baz:FileB?
}

Now if you modify FileA, the compiler will obviously mark FileA to be recompiled. It will also recompile FileB (that would be OK based on the changes to FileA), but also FileC because FileB is recompiled, and that is pretty bad because FileC never uses FileA here.

So I hope they improve that dependency tree solver... I've opened a radar with this sample code.

UPDATE With Xcode 7 beta 5 and Swift 2.0

Yesterday Apple released the beta 5 and inside the release notes we could see:

Swift Language & Compiler • Incremental builds: changing just the body of a function should no longer cause dependent files to be rebuilt. (15352929)

I have given it a try and I must say it is working really (really !) well now. They greatly optimized the incremental builds in swift.

I highly recommend you create a swift2.0 branch and keep your code up to date using XCode 7 beta 5. You will be pleased by the enhancements of the compiler (however I'd say the global state of XCode 7 is still slow & buggy)

解决方案

Well, it turned out that Rob Napier was right. It was one single file (actually one method) that was causing the compiler to go berzek.

Now don't get me wrong. Swift does recompile all your files each time, but the great thing now, is that Apple added real-time compilation feedback over the files it compiles, so Xcode 6 GM now shows which Swift files are being compiled and the status of compilation in real time as you can see in this screenshot:

So this comes very handy to know which of your files is taking so long. In my case it was this piece of code:

var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
        "url" : self.url?.absoluteString ?? "",
        "title" : self.title ?? ""
        ])

return dic.copy() as NSDictionary

because the property title was of type var title:String? and not NSString. The compiler was going crazy when adding it to the NSMutableDictionary.

Changing it to:

var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
        "url" : self.url?.absoluteString ?? "",
        "title" : NSString(string: self.title ?? "")
        ])

return dic.copy() as NSDictionary

made the compilation go from 10/15 seconds (maybe even more) down to a single second... amazing.

这篇关于为什么Swift的编译时间这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆