Swift 显式与推断类型:性能

Posted

技术标签:

【中文标题】Swift 显式与推断类型:性能【英文标题】:Swift Explicit vs. Inferred Typing : Performance 【发布时间】:2014-08-26 15:42:42 【问题描述】:

我正在阅读有关 Swift (http://www.raywenderlich.com/74438/swift-tutorial-a-quick-start) 的教程,它预先设置为不显式设置类型,因为这样更具可读性。

我不太同意这一点,但这不是问题所在。我的问题是:就性能(编译器...)而言,明确设置类型是否更有效?

例如,这:var hello: Int = 56 是否比这更有效:var tutorialTeam = 56

【问题讨论】:

因为它是一个编译器检查,它根本不会影响你的应用程序的性能。 let a = 1let a:Int = 1 是完全等价的。如果您使用 alt+click 检查a,它会说它是Int 类型。 编译器在将其设置为 Int 之前不会检查任何类型的 1 吗? 嗯?也许您不太了解静态类型推断的意义。当您忽略注释时,并不意味着编译器只是将变量视为必须解决的一些通用寄存器值。类型推断首先发生,然后变量在所有使用它的表达式中都被视为该类型。如果由于某种原因编译器无法推断出变量的类型,则会成为类型错误。运行时什么都不会发生。没有性能提升。 @CodaFi 第二个你添加的建议作为答案;很多读者都不清楚编译和运行时间的区别,你解释得很好。 文章在这一点上的建议似乎很糟糕。明确一个值的类型将使代码更易于阅读。 【参考方案1】:

使用显式类型的代码和使用类型推断的代码之间性能没有差异。在每种情况下编译的输出都是相同的。

当您省略类型时,编译器会简单地推断它。

accepted answer 中观察到的非常小的差异只是您通常的微基准测试人工制品,不能信任!

是否包含显式类型是个人喜好问题。在某些情况下,它可能会使您的代码更具可读性。

它对您的代码产生影响的唯一情况是当您想要指定与编译器将推断的类型不同的类型时。举个例子:

var num = 2

上面的代码推断numInt,因为它是用整数字面量初始化的。但是,您可以将其“强制”为Double,如下所示:

var num: Double = 2

【讨论】:

这是正确答案。编译出来的结果是相同的,因此显式或隐式类型实际上不可能对性能产生任何影响。 @PaulManta - 谢谢,看到接受的答案公然错误让我很恼火! 检查编译输出的好主意。 Whether or not you include the explicit type is a matter of taste. In some contexts it might make your code more readable. 没错!从长远来看,添加类型注释“以提高编译器性能”会导致代码臃肿且可读性降低。同时,由于 Swift 编译器工程师的工作,编译器性能正在提高 - 这将使添加的类型注释变得无用。【参考方案2】:

根据我的经验,在使用显式类型和推断类型时,编译速度会对性能产生巨大影响。我的大部分慢速编译代码都已通过显式键入变量来解决。

似乎 Swift 编译器在这方面仍有改进的空间。尝试对您的一些项目进行基准测试,您会看到很大的不同。

这是我在how to speed up slow Swift compile times 上写的一篇文章,以及如何找出导致它的原因。

【讨论】:

【参考方案3】:

类型推断不会影响您给定示例中的性能。但是,我确实发现,在 Swift 数组中指定类型确实会显着影响性能。

例如,下面的方法对Any 类型的数组进行洗牌。

class func shuffleAny(inout array: [Any]) 
    for (var i = 0; i < array.count; i++) 
        let currentObject: Any = array[i]
        let randomIndex = Int(arc4random()) % array.count
        let randomObject: Any = array[randomIndex]

        array[i] = randomObject;
        array[randomIndex] = currentObject
    

上面的函数实际上比我让这个函数采用Int的数组而不是像这样慢得多

class func shuffleIntObjects(inout array: [Int]) 
    for (var i = 0; i < array.count; i++) 
        let currentObject: Int = array[i]
        let randomIndex = Int(arc4random()) % array.count
        let randomObject: Int = array[randomIndex]

        array[i] = randomObject;
        array[randomIndex] = currentObject
    

使用 [Any] 的函数以 0.537 秒 3% STDEV 计算 100 万个 Int 对象。并且使用[Int] 的函数以 0.181 秒 2% STDEV 对 100 万个 Int 对象进行计时。

您可以查看这个 repo (https://github.com/vsco/swift-benchmarks),其中详细介绍了 Swift 中更多有趣的基准。我最喜欢的一个是 Swift 泛型在上面提到的测试条件下表现很差

【讨论】:

以上是关于Swift 显式与推断类型:性能的主要内容,如果未能解决你的问题,请参考以下文章

当完成处理程序显式使用 @escaping 时,Swift 推断完成处理程序闭包是默认的 @nonescaping 而不是 @escaping

SwiftUI 如何修复“无法推断复杂的闭包返回类型;添加显式类型以消除歧义”

无法推断复杂的闭包返回类型;添加显式类型以消除歧义

OpenGL着色器的显式与自动属性位置绑定

显式与隐式启动Activity

网站后端_Python+Flask.0008.FLASK响应相关之隐式显式与自定义响应?