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 = 1
和 let a:Int = 1
是完全等价的。如果您使用 alt+click 检查a
,它会说它是Int
类型。
编译器在将其设置为 Int 之前不会检查任何类型的 1 吗?
嗯?也许您不太了解静态类型推断的意义。当您忽略注释时,并不意味着编译器只是将变量视为必须解决的一些通用寄存器值。类型推断首先发生,然后变量在所有使用它的表达式中都被视为该类型。如果由于某种原因编译器无法推断出变量的类型,则会成为类型错误。运行时什么都不会发生。没有性能提升。
@CodaFi 第二个你添加的建议作为答案;很多读者都不清楚编译和运行时间的区别,你解释得很好。
文章在这一点上的建议似乎很糟糕。明确一个值的类型将使代码更易于阅读。
【参考方案1】:
使用显式类型的代码和使用类型推断的代码之间性能没有差异。在每种情况下编译的输出都是相同的。
当您省略类型时,编译器会简单地推断它。
accepted answer 中观察到的非常小的差异只是您通常的微基准测试人工制品,不能信任!
是否包含显式类型是个人喜好问题。在某些情况下,它可能会使您的代码更具可读性。
它对您的代码产生影响的唯一情况是当您想要指定与编译器将推断的类型不同的类型时。举个例子:
var num = 2
上面的代码推断num
是Int
,因为它是用整数字面量初始化的。但是,您可以将其“强制”为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