Inout vs 通过引用传递 swift 优化
Inout vs pass by reference swift optimization
我有一个非常大的数字列表,我想将它传递给一个函数来对其进行一些操作。最初,我创建了一个带有 inout 属性 的函数。正如许多人所知,swift 中的 inout 不会通过引用传递,而是对函数进行初始复制,然后将值复制回 return。这听起来很贵。我决定将我的列表包装在 class 中并通过引用传递,以优化和减少复制时间。有趣的是,inout 函数似乎比按引用传递函数更快。我什至对 inout 变量进行了操作,使编译器进行写时复制。知道为什么 inout 函数比按引用传递更快吗?
class ReferencedContainer {
var container = [Int:Bool]()
}
func printTimeElapsedWhenRunningCode(title:String, operation:()->()) {
let startTime = CFAbsoluteTimeGetCurrent()
operation()
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
print("Time elapsed for \(title): \(timeElapsed) s.")
}
func inoutTest(list: inout [Int]?) -> [Int]? {
list![0]=1
return list
}
func refTest(list: ReferencedContainer) -> ReferencedContainer {
list.container[0] = true
return list
}
var list : [Int]? = [Int]()
for i in 0...10000 {
list?.append(i)
}
var ref = ReferencedContainer()
for i in list!
{
ref.container[i] = true
}
printTimeElapsedWhenRunningCode(title: "refTest", operation: { refTest(list: ref)})
printTimeElapsedWhenRunningCode(title: "inout", operation: { inoutTest(list: &list)})
refTest 经过的时间:0.0015590190887451172 秒。
inout 经过的时间:0.00035893917083740234 秒。
As many know, inout in swift does NOT pass by reference, rather it makes an initial copy to the function then copies the values back on the return. This sounds expensive.
不是。它正在复制 [Int: Bool]
(a.k.a. Dictionary<Int, Bool>
) 的一个实例,它只是一个指针。用 print(MemoryLayout<[Int: Bool]>.size)
.
亲自看看
在许多可能的情况下,有两件事需要考虑:
inout
可以使用call-by-reference作为优化,参见In-Out Parameters
- 你的两个测试很不一样,一个使用可选值和一个数组,另一个使用字典。你也只是在测试一个单一的突变,尝试做更多。您应该拥有的唯一区别是结构与 class,如果您尝试获得相似的速度或其中一个速度比另一个更快 – 无论哪种方式。
我有一个非常大的数字列表,我想将它传递给一个函数来对其进行一些操作。最初,我创建了一个带有 inout 属性 的函数。正如许多人所知,swift 中的 inout 不会通过引用传递,而是对函数进行初始复制,然后将值复制回 return。这听起来很贵。我决定将我的列表包装在 class 中并通过引用传递,以优化和减少复制时间。有趣的是,inout 函数似乎比按引用传递函数更快。我什至对 inout 变量进行了操作,使编译器进行写时复制。知道为什么 inout 函数比按引用传递更快吗?
class ReferencedContainer {
var container = [Int:Bool]()
}
func printTimeElapsedWhenRunningCode(title:String, operation:()->()) {
let startTime = CFAbsoluteTimeGetCurrent()
operation()
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
print("Time elapsed for \(title): \(timeElapsed) s.")
}
func inoutTest(list: inout [Int]?) -> [Int]? {
list![0]=1
return list
}
func refTest(list: ReferencedContainer) -> ReferencedContainer {
list.container[0] = true
return list
}
var list : [Int]? = [Int]()
for i in 0...10000 {
list?.append(i)
}
var ref = ReferencedContainer()
for i in list!
{
ref.container[i] = true
}
printTimeElapsedWhenRunningCode(title: "refTest", operation: { refTest(list: ref)})
printTimeElapsedWhenRunningCode(title: "inout", operation: { inoutTest(list: &list)})
refTest 经过的时间:0.0015590190887451172 秒。
inout 经过的时间:0.00035893917083740234 秒。
As many know, inout in swift does NOT pass by reference, rather it makes an initial copy to the function then copies the values back on the return. This sounds expensive.
不是。它正在复制 [Int: Bool]
(a.k.a. Dictionary<Int, Bool>
) 的一个实例,它只是一个指针。用 print(MemoryLayout<[Int: Bool]>.size)
.
在许多可能的情况下,有两件事需要考虑:
inout
可以使用call-by-reference作为优化,参见In-Out Parameters- 你的两个测试很不一样,一个使用可选值和一个数组,另一个使用字典。你也只是在测试一个单一的突变,尝试做更多。您应该拥有的唯一区别是结构与 class,如果您尝试获得相似的速度或其中一个速度比另一个更快 – 无论哪种方式。