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是一个字

我已将Swift编译器标志
-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”
将编译时间减半。这与我的第一个代码块相当<代码>=比回答您的问题“90ms是不是太低了?”时的理解速度要快。在我看来,这应该是很容易编译的。这可能是一种类型推断?如果将type
let 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)"
}