我应该将 let 值从 for 循环中取出以获得更好的性能吗?

Posted

技术标签:

【中文标题】我应该将 let 值从 for 循环中取出以获得更好的性能吗?【英文标题】:Should I put let values out of for loops to get better performance? 【发布时间】:2016-03-20 22:35:08 【问题描述】:

例如,如果我有这样的代码

for i in 1 ... 10000 
    let someValue = 9
    ...

我应该将 let 值排除在循环之外,以便获得更好的性能还是完全没有必要?

autoreleasepool 
    let someValue = 9
    for i in 1 ... 10000 
        ...
    

有什么想法吗?

【问题讨论】:

反问:为什么要把它放在循环体中? @vikingosegundo 因为它只需要在那里。这也是我在其他代码中使用 autoreleasepool 的原因,因为我不想在其他范围内使用它。 autoreleasepool 对于范围界定来说是一个相当糟糕的主意。使用方法和隐式创建更小的范围。 它不仅与花费的时间有关。这是冤枉的,如果您始终使用相同的值,则无需每次分配内存。您在每个周期中分配和释放内存,如果您使用比 Int 更大的对象,则需要时间和内存。 【参考方案1】:

外面

let a = NSDate()
for i in 1...100 
    let someValue = a
    print("Hello World!")

let b = NSDate()
let c: Double = b.timeIntervalSinceDate(a)
print(c)

let d = NSDate()
let someValue = a
for i in 1...100 
    print("Hello World!")

let e = NSDate()
let f: Double = e.timeIntervalSinceDate(d)
print(f)

在运行最新版本 OSX 的 MacBook Air 上的操场上 c = 0.092 和 f = 0.022

看来您需要改写问题。如果常量不会发生变异,那么它应该在循环之外。循环用于需要变异的重复代码。外部总是更好,因为内部你必须分配另一个实例 i 次而不是一次。

【讨论】:

你的方法很适合我。但是,我想知道如果代码编译在 .swift 文件中,答案是否相同?由于操场是逐行运行的。 不幸的是,游乐场不是测试这个的最佳场所,但如果您将代码作为源文件添加(到游乐场),甚至创建一个可以调整优化的新项目,您可以获得更多可靠的结果。【参考方案2】:

对于可以快速初始化的类型,您可能不需要使用第二个版本,因为这只会带来很小的性能提升。

编译器也可以优化它。尤其是在 structsenums 的情况下,因为它们根本无法变异。虽然使用类你可以改变它的内容,如果编译器不能在编译时检查它是否被改变,它就不能被优化。

总而言之,对于 Int 这样一个简单的案例,您可以使用哪一个,因为假设您在 for循环。

注意:针对不同的作用域,Swift 2 引入了do

do 
    let someValue = 9
    for i in 1 ... 10000 
        ...
    

【讨论】:

我创建了一个新的命令行项目并使用@CodyWeaver 的方法。在 100 万次循环的测试中,性能损失仅为 1/1000。所以我相信任何一种方式都可以。谢谢。 我已经给了你一个赞成票,这使得它从 -1 变为 0。我不知道为什么会有反对票,因为我认为你的答案不应该被反对。 @CodyWeaver OwenZhao 如果与此问题无关,请移步聊天。 @Qbyte 我在哪里可以找到聊天?

以上是关于我应该将 let 值从 for 循环中取出以获得更好的性能吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用Spring Security + CAS获得循环重定向,但应该正常工作

如何在 for 循环中使用动态键值从 JSON 数组获取值?科特林

将随机值从数组复制到对象无法获得稳定的结果

“for”循环出现问题 - 关于长度的警告消息

我应该使用迭代器还是 for 循环来迭代?

使用循环将值从 C++ 中的一维数组添加到二维数组中