Swift 快速类型检查在非常短的功能上花费的时间太长
我已将Swift编译器标志Swift 快速类型检查在非常短的功能上花费的时间太长,swift,type-inference,Swift,Type Inference,我已将Swift编译器标志-warn long function body设置为90毫秒,以查看我的项目中哪些函数的编译时间过长(由于类型检查) 我有以下方法: func someKey(_ sectionType: SectionType, row: Int) -> String { let suffix = row == 0 ? "top" : "content" return "\(sectionType)_\(suffix)" } (SectionType是一个字
-warn long function body
设置为90毫秒,以查看我的项目中哪些函数的编译时间过长(由于类型检查)
我有以下方法:
func someKey(_ sectionType: SectionType, row: Int) -> String {
let suffix = row == 0 ? "top" : "content"
return "\(sectionType)_\(suffix)"
}
(SectionType
是一个字符串支持的枚举)
如上所述,2017年MacBook Pro需要96毫秒。我尝试的第一件事是绕过字符串插值,使用\(sectionType.rawValue)
而不是\(sectionType)
,但现在它给了我106 ms。错误的举动
接下来,我改变了:
let suffix = row == 0 ? "top" : "content"
致:
警告消失了,因此是三元运算符引起了问题
我试过这样做:
let suffix: String = { // Note the type annotation!
if row == 0 {
return "top"
}
return "content"
}()
…但现在是需要97毫秒的闭包(整个函数,101)
我甚至尝试了更明确的方式:
let suffix: String = {
if row == 0 {
return String("top")
} else {
return String("content")
}
}()
…我得到的结果是:94毫秒;功能:98毫秒
发生了什么事?
我的90毫秒限制是否太低?我知道有(是?)一个使用字典文本的类型检查错误,但这似乎是完全不同的
我的环境是Xcode 8.3.2(8E2002),
Swift:Apple Swift版本3.1(swiftlang-802.0.53 clang-802.0.42)
等等!还有更多… 我试过这个函数体:
func someKey(_ sectionType: SectionType, row: Int) -> String {
if row == 0 {
return "\(sectionType.rawValue)_top"
} else {
return "\(sectionType.rawValue)_content"
}
}
…需要97ms~112ms
附录:我将函数和枚举移植到一个干净的最小项目(单视图应用程序)中,设置了相同的警告,但没有发生。我确信整个项目在某种程度上影响了这一方法,但还不太清楚如何
附录2:我测试了我的函数的静态版本:无论
行的值如何,都使用固定后缀“top”(这需要不到90毫秒的时间,并且不会触发任何警告),但是添加了以下如果块:
func someKey(_ sectionType: SectionType, row: Int) -> String {
if row == 0 {
print("zero")
} else {
print("non-zero")
}
let suffix: String = "top"
return "\(sectionType)_\(suffix)"
}
这让我回到96~98毫秒因此,将行与零进行比较时会出现问题?
解决方法:我一直在玩我的代码,不知怎的,我发现如果我用switch
语句替换if
块,问题就会消失:
func someKey(_ sectionType: SectionType, row: Int) -> String {
let suffix: String = {
switch row {
case 0:
return "top"
default:
return "content"
}
}()
return "\(sectionType)_\(suffix)"
}
<>(我不会回答我自己的问题,因为我不认为这是对事实的解释)< P > >我认为这是三元运算符。
我在Xcode 11中得到了类似的结果(~93ms),但编译时间减少到了~23ms,原因是:
func someKey(_ sectionType: SectionType, row: Int) -> String {
var suffix = "top"
if row != 0 {
suffix = "content"
}
return "\(sectionType)_\(suffix)"
}
通过改变这一行的逻辑,我认为我们可以证明它是三值逻辑,因为该方法减少到~1ms。我刚把这一行写成布尔值
func someKey(_ sectionType: SectionType, row: Bool) -> String {
let suffix = row ? "top" : "content"
return "\(sectionType)_\(suffix)"
}
同样(没有双关语)将三元逻辑更改为let suffix=row!=0 ? “top”:“content”
将编译时间减半。这与我的第一个代码块相当<代码>=对于Swift来说,code>比回答您的问题“90ms是不是太低了?”时的理解速度要快。在我看来,这应该是很容易编译的。这可能是一种类型推断?如果将typelet suffix:String=…
添加到第一个示例中会发生什么情况?作为我上面评论的一部分。有一个关于类型检查和类型推断的非常好的视频(我会找到一个链接)。前者很容易,而后者很难。看看这段视频,你仍然需要很长的编译时间:(如果你把第一个例子的返回行改成一个静态的东西,比如return“Hello,world!”会怎么样
?只是为了检查它是第一行还是最后一行的插值。不进行比较的编译时间是多少?(将“长时间”限制设置为5毫秒以再次触发警告)。从我的测试中,我发现1.字符串插值可能需要时间”(sectionType)uz(后缀)“2.字符串构造函数可能需要时间:String(“top”)
(可能是因为重载的构造函数)
func someKey(_ sectionType: SectionType, row: Bool) -> String {
let suffix = row ? "top" : "content"
return "\(sectionType)_\(suffix)"
}