我看了著名的为什么处理排序数组比未排序数组更快?,并决定尝试使用其他语言如Swift进行实验。我对两个非常相似的代码片段之间的运行时间差异感到惊讶。
在Swift中,可以通过直接方式或下标方式访问数组中的元素,在for-in循环中。例如,这个代码:
通过
我并不真正知道后台的下标实现方式,但我认为在 Swift for-in 循环中直接访问元素只是语法糖。
以下是计时器的详细信息。我正在使用带有 Swift 4.1 的 Xcode 9.4.1,在一台早期的 2015 MacBook Air 上运行命令行项目。
这是我使用的Swift代码,我只修改了第二个嵌套循环:
在Swift中,可以通过直接方式或下标方式访问数组中的元素,在for-in循环中。例如,这个代码:
for i in 0..<size {
sum += data[i]
}
可以写成:
for element in data {
sum += element
}
通过
size
参数来指定 data
数组中可求和的元素个数。
所以,我在 Swift 中实现了与我在第一段提到的问题相同的算法(下面是代码),让我惊讶的是第一种方法大约比第二种方法快 5 倍。我并不真正知道后台的下标实现方式,但我认为在 Swift for-in 循环中直接访问元素只是语法糖。
问题
我的问题是两种for-in
语法之间有什么区别,为什么使用下标会更快?以下是计时器的详细信息。我正在使用带有 Swift 4.1 的 Xcode 9.4.1,在一台早期的 2015 MacBook Air 上运行命令行项目。
// Using Direct Element Access
Elapsed Time: 8.506288427
Sum: 1051901000
vs
// Using Subscript
Elapsed Time: 1.483967902
Sum: 1070388000
奖励问题: 为什么在Swift中执行速度比C++慢100倍 (两者在同一台Mac上在Xcode项目中执行)?例如,在C++中重复100,000次几乎需要与在Swift中重复1,000次相同的时间。我的第一个猜测是Swift是比C++更高级的语言,而且Swift会执行更多的安全检查等。
这是我使用的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)")
-O
得到了与您相同的结果。因此,总结一下,当未经优化时,第二个循环方法比使用下标要慢得多。 - Louis LacSequence.makeIterator(),IteratorProtocol.next()
),如果它们没有被优化掉(在-O
中已经优化掉了),则会拖慢运行速度。 - Alexander