在Swift中,可以在for-in循环中以直接方式或使用下标访问数组中的元素.例如这段代码:
for i in 0..<size { sum += data[i] }
可写:
for element in data { sum += element }
随着数据长度和数据的大小,可汇总元素的数组.
所以,我只是在Swift(代码吼叫)中实现了与我在第一段中提到的问题相同的算法,令我惊讶的是第一种方法比第二种方法快大约5倍.
我真的不知道后台下标的实现,但我认为直接访问Swift for-in循环中的元素只是语法糖.
题
我的问题是两个for-in语法之间的区别是什么以及为什么使用下标更快?
这里是计时器的细节.我在2015年初的MacBook Air上使用Xcode 9.4.1和Swift 4.1以及Commande Line项目.
// Using Direct Element Access Elapsed Time: 8.506288427 Sum: 1051901000
VS
// Using Subscript Elapsed Time: 1.483967902 Sum: 1070388000
额外的问题:为什么Swift中的执行速度比C中慢100倍(在n Xcode项目中都在同一台Mac上执行)?例如,在C中100,000次重复几乎与Swift中的1,000次重复相同.我的第一个猜测是,Swift是一种比C语言更高级的语言,例如Swift运行更多的安全检查.
import Foundation import GameplayKit let size = 32_768 var data = [Int]() var sum = 0 var rand = GKRandomdistribution(lowestValue: 0,highestValue: 255) for _ in 0..<size { data.append(rand.nextInt()) } // data.sort() let start = dispatchTime.Now() for _ in 0..<1_000 { // Only the following for-in loop changes for i in 0..<size { if data[i] <= 128 { sum += data[i] } } } let stop = dispatchTime.Now() let nanoTime = stop.uptimeNanoseconds - start.uptimeNanoseconds let elapsed = Double(nanoTime) / 1_000_000_000 print("Elapsed Time: \(elapsed)") print("Sum: \(sum)")
解决方法
为了证明这一点,我更新了您的代码,添加了两个方法,一个使用下标,另一个使用for-in.
import Foundation import GameplayKit let size = 32_768 var data = [Int]() var sum = 0 var rand = GKRandomdistribution(lowestValue: 0,highestValue: 255) for _ in 0..<size { data.append(rand.nextInt()) } // data.sort() func withSubscript() { let start = dispatchTime.Now() for _ in 0..<1_000 { for i in 0..<size { if data[i] <= 128 { sum += data[i] } } } let stop = dispatchTime.Now() let elapsed = Double(stop.uptimeNanoseconds - start.uptimeNanoseconds) / 1_000_000_000 print("With subscript:") print("- Elapsed Time: \(elapsed)") print("- Sum: \(sum)") } func withForIn() { let start = dispatchTime.Now() for _ in 0..<1_000 { for element in data { if element <= 128 { sum += element } } } let stop = dispatchTime.Now() let elapsed = Double(stop.uptimeNanoseconds - start.uptimeNanoseconds) / 1_000_000_000 print("With for-in:") print("- Elapsed Time: \(elapsed)") print("- Sum: \(sum)") } withSubscript() withForIn()
我将该代码保存到名为array-subscripting.swift的文件中.
然后,从命令行,我们可以在没有任何优化的情况下运行它,如下所示:
$swift array-subscripting.swift With subscript: - Elapsed Time: 0.924554249 - Sum: 1057062000 With for-in: - Elapsed Time: 5.796038213 - Sum: 2114124000
正如你在帖子中提到的,性能有很大差异.
使用优化编译代码时,这种差异可以忽略不计:
$swiftc array-subscripting.swift -O $./array-subscripting With subscript: - Elapsed Time: 0.110622556 - Sum: 1054578000 With for-in: - Elapsed Time: 0.11670454 - Sum: 2109156000
如您所见,两种解决方案都比以前更快,并且在时间执行上非常相似.
回到原来的问题,下标提供了对内存的直接访问,这在连续数组的情况下非常有效,其中元素在内存中彼此相邻存储.
另一方面,for-in循环从数组中创建每个元素的不可变副本,这会导致性能损失.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。