Inout против проходной оптимизации Swift - PullRequest
0 голосов
/ 25 июня 2019

У меня очень большой список чисел, и я хотел бы передать его в функцию, чтобы выполнить некоторые манипуляции с ним.Первоначально я создал функцию со свойством inout.Как многие знают, inout в swift НЕ передается по ссылке, скорее, он делает начальную копию функции, а затем копирует значения обратно в возвращаемое значение.Это звучит дорого.Я решил обернуть свой список в класс и перейти по ссылке, чтобы оптимизировать и сократить время на копирование.Интересно, что кажется, что функция 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 с.

Время, истекшее для ввода: 0,00035893917083740234 с.

Ответы [ 2 ]

2 голосов
/ 25 июня 2019

Как многие знают, inout в swift НЕ передается по ссылке, скорее, он делает начальную копию функции, а затем копирует значения обратно в возвращаемое значение.Это звучит дорого.

Это не так.Он копирует экземпляр [Int: Bool] (он же Dictionary<Int, Bool>), который является только одним указателем.Убедитесь сами, с print(MemoryLayout<[Int: Bool]>.size).

1 голос
/ 25 июня 2019

Две вещи для рассмотрения, из многих возможных:

  1. inout может использовать вызов по ссылке в качестве оптимизации, см. Параметры входа-выхода
  2. Ваши два теста довольно разные: один использует опциональные значения и массив, другой - словарь. Вы также тестируете только одну мутацию, попробуйте сделать больше. Единственное отличие, которое вы должны иметь, это структура против класса, и если вы попытаетесь, вы можете получить аналогичные скорости или одну из них быстрее, чем другую - в любом случае.
...