Swift Struct vs. Class Performance

In dem Spiel, dass Michael und ich in dem Projekt derbe.cool entwickeln nutzen wir immutable structs, die bei jeder Nutzeraktion mehrmals kopiert und angepasst werden. In diesem Kontext habe ich mir die Frage gestellt, was der Performance-Unterschied im Vergleich zum kopieren einer Klasse ist.

Ein Vergleich von einfachen Structs und Klassen mit nur value types zeigt einen deutlichen Unterschied, der auch bei reference types nicht anders ist.

let iterations = 1000000

// simple
struct SimpleStruct {
    let value: UInt8
    let anotherValue: UInt16
    
    func setValue(value: UInt8) -> SimpleStruct {
        return SimpleStruct(value: value, anotherValue: anotherValue)
    }
}

class SimpleClass {
    let value: UInt8
    let anotherValue: UInt16
    
    init(value: UInt8, anotherValue: UInt16) {
        self.value = value
        self.anotherValue = anotherValue
    }
    
    func setValue(value: UInt8)  -> SimpleClass {
        return SimpleClass(value: value, anotherValue: anotherValue)
    }
}

let structStartDate = NSDate()
var aStruct = SimpleStruct(value: 1, anotherValue: 2)

for v in 0..<iterations {
    aStruct = aStruct.setValue(UInt8(v % 255))
}
let structDuration = NSDate().timeIntervalSinceDate(structStartDate)
puts("simple struct \(structDuration)")

let classesStartDate = NSDate()
var aClass = SimpleClass(value: 1, anotherValue: 2)

for v in 0..<iterations {
    aClass = aClass.setValue(UInt8(v % 255))
}
let classDuration = NSDate().timeIntervalSinceDate(classesStartDate)
puts("simple class \(classDuration)")





// moreComplex
struct ComplexStruct {
    let values: [UInt8]
    
    func setFirstValue(value: UInt8) -> ComplexStruct {
        var newValues = values
        newValues[0] = value
        return ComplexStruct(values: newValues)
    }
}

class ComplexClass {
    let values: [UInt8]
    
    init(values: [UInt8]) {
        self.values = values
    }
    
    func setFirstValue(value: UInt8)  -> ComplexClass {
        var newValues = values
        newValues[0] = value
        return ComplexClass(values: newValues)
    }
}

let complexStructStartDate = NSDate()
var complexStruct = ComplexStruct(values: [1])

for v in 0..<iterations {
    complexStruct = complexStruct.setFirstValue(UInt8(v % 255))
}
let complexStructDuration = NSDate().timeIntervalSinceDate(complexStructStartDate)
puts("complex struct \(structDuration)")

let complexClassesStartDate = NSDate()
var complexClass = ComplexClass(values: [1])

for v in 0..<iterations {
    complexClass = complexClass.setFirstValue(UInt8(v % 255))
}
let complexClassDuration = NSDate().timeIntervalSinceDate(complexClassesStartDate)
puts("complex class \(classDuration)")

simple struct 0.00943303108215332
simple class 0.841512024402618
complex struct 0.00943303108215332
complex class 0.841512024402618