Swift明确类型与推断类型:性能比较

15

我正在阅读一篇有关Swift的教程 (http://www.raywenderlich.com/74438/swift-tutorial-a-quick-start),它建议不要显式设置类型,因为这种方式更易于阅读。

我并不完全同意这一点,但这不是我的问题。我的问题是:在性能方面(编译器...)是否显式设置类型更有效率?

例如,这样写:var hello: Int = 56 是否比这样写:var tutorialTeam = 56 更高效?


3
由于这是编译器检查,因此不会影响您的应用程序性能。 let a = 1let a:Int = 1 是完全等效的。如果您使用 alt+单击 检查 a,它将显示为 Int 类型。 - Jack
1
编译器不会在将1设置为Int之前检查其类型吗? - user2462805
4
嗯?也许你还没有完全理解静态类型推断的要点。当你省略注释时,并不意味着编译器会把变量视为必须绕过的某些通用寄存器值。首先进行类型推断,然后在所有使用该变量的表达式中,都将其视为该类型。如果出现编译器无法推断变量类型的情况,则会产生类型错误。这一切都不会发生在运行时。没有性能增益可言。 - CodaFi
1
@CodaFi,我支持你把这个建议作为一个答案加入进来;很多读者并不清楚编译时间和运行时间之间的区别,而你解释得很好。 - jrturton
1
文章关于这一点的建议似乎非常糟糕。清晰地表明一个值的类型将使代码更易于阅读。 - Paul Manta
显示剩余2条评论
3个回答

25

使用显式类型和类型推断的代码在性能上没有区别。在每种情况下,编译输出是相同的。

当省略类型时,编译器会自动推断它。

接受的答案中观察到的非常小的差异只是通常微型基准测试工具的产物,并且不能被信任!

是否包括显式类型是品味问题。在某些情况下,可能会使你的代码更易读。

唯一使你的代码有所区别的情况是当你想指定与编译器推断的不同类型时。例如:

var num = 2

上述代码表明num是一个Int,因为它被初始化为整数字面量。然而,你可以通过以下方式“强制”将其变成一个Double

var num: Double = 2

这是正确的答案。编译输出相同,因此显式或隐式类型在性能上没有任何区别。 - Paul Manta
@PaulManta - 谢谢,看到被明显错误的答案被接受让我很烦恼! - ColinE
检查编译输出是一个好主意。 - Dave Wood
是否包含显式类型是个人口味问题。在某些情况下,这可能会使您的代码更易读。没错!添加类型注释“以提高编译器性能”将导致代码变得臃肿且难以阅读。与此同时,Swift编译器工程师的工作正在改善编译器性能 - 这将使添加的类型注释变得无用。 - Igor Makarov

4

根据我的经验,在使用显式类型与隐式类型时,编译速度会有很大的性能影响。通过对变量进行显式类型化,我成功解决了大部分编译缓慢的代码。

似乎Swift编译器在这方面仍有改进的空间。尝试对你的一些项目进行基准测试,你会发现巨大的差异。

这里是我写的一篇关于如何加速Swift编译时间以及如何找到其原因的文章:如何加快Swift编译时间


-1

类型推断不会影响您所给出的示例中的性能。然而,我发现在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] 的函数在处理100万个Int对象时,计时为0.537秒,标准偏差为3%。而使用 [Int] 的函数在处理100万个Int对象时,计时为0.181秒,标准偏差为2%。

您可以查看这个仓库(https://github.com/vsco/swift-benchmarks),其中详细介绍了Swift中更多有趣的基准测试。我最喜欢的之一是,在上述测试条件下,Swift泛型表现非常糟糕。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接