swift - 使用带范围的 for-in 循环时的性能问题
问题描述
Swift 提供了一个 for-in 风格的 for 循环来替代 C 风格的 for 循环。我们也可以将这种 for-in 循环与Range
and一起使用ClosedRange
。
for i in 0..<100 {
// do something.
}
但是,在使用带范围的 for-in 循环时会出现一些性能问题,尤其是当存在嵌套的 for 循环时。
我使用 XCTestmeasure
来测试三种循环:
- for-in 循环
ClosedRange
- for-in 循环
Range
- while循环
final class LeetcodeSolutionsTests: XCTestCase {
var count: Int = 1000
func testForInClosedRange() {
// Time: 1.016 sec
measure {
for i in 1...count {
for j in 1...count {
let _ = i + j
}
}
}
}
func testForInRange() {
// Time: 0.542 sec
measure {
for i in 1...count {
for j in 1..<(count + 1) {
let _ = i + j
}
}
}
}
func testWhile() {
// Time: 0.015 sec
measure {
for i in 1...count {
var j = 1
while j < count + 1 {
let _ = i + j
j += 1
}
}
}
}
}
从示例中,for-in 循环 withRange
比 for-in 循环 with 快 2 倍ClosedRange
。而while循环比它们都快得多。
我猜 for-in 循环会做一些额外的工作,而且会有一些细微的性能差异是有道理的。我没想到的是性能差异如此之大。
解决方案
您的问题仅出现在 Debug 配置中,因为编译器会生成大量访问检查代码。
如果你
- 以使用变量的方式修改代码(以防止编译器丢弃所有未使用的代码)
- 然后在发布模式下运行它
对于每种循环,您都会得到完全相同的结果:
func measure(txt:String = #function, c:()->()) {
let start=Date()
c()
let end = Date()
let duration = end.timeIntervalSinceReferenceDate-start.timeIntervalSinceReferenceDate
print ("\(txt) - Duration: \(duration)")
}
final class LeetcodeSolutionsTests {
var count: Int = 1000
func testForInClosedRange() {
// Time: 0.001672 sec
var result:Int = 0
measure {
for i in 1...count {
for j in 1...count {
result += i + j
}
}
}
print (result)
}
func testForInRange() {
// Time: 0.001671
var result:Int = 0
measure {
for i in 1...count {
for j in 1..<(count + 1) {
result += i + j
}
}
}
print (result)
}
func testWhile() {
// Time: 0.001670 sec
var result:Int = 0
measure {
for i in 1...count {
var j = 1
while j < count + 1 {
result += i + j
j += 1
}
}
}
print (result)
}
}
let t = LeetcodeSolutionsTests()
t.testForInClosedRange()
t.testForInRange()
t.testWhile()
然后给你:
testForInClosedRange() - Duration: 0.0016720294952392578
1001000000
testForInRange() - Duration: 0.0016709566116333008
1001000000
testWhile() - Duration: 0.0016709566116333008
1001000000
推荐阅读
- mysql - 如何防止 Hive Create Table 将数据中带有逗号“,”的列拆分为两列
- caching - 如何模拟 python 装饰器参数?
- node.js - 使用 Node.js 以 JSON 格式发送 PDF 文件时使用什么数组格式
- python - Odoo 13 导入联系人 csv 方法
- r - r中的列名到矩阵格式
- drake - 将广义力添加到线性化(或 LQR)MultiBodyPlant 的最佳方法?
- python - 插入几个新列,其值基于熊猫数据框中的另一列
- python - 具有多项式特征的线性回归
- python-3.x - 如何在 FastHTTPUser 的 locust 负载测试工具中发出发布请求之前将 cookie 配置或设置为 json
- flutter - 如何灵活地只在Column中分配空白空间?