Swift Struct vs. Class Performance

In the game that Michael and I are developing for our project derbe.cool we frequently use immutable structs that are copied and mutated multiple times for every user activity. That’s when I started to wonder what the performance difference is between copying a struct vs. a class.

A comparison of simple structs and classes using only value types or only referency types shows a huge difference.

import Foundation

let iterations = 10

// 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 = Date()
var aStruct = SimpleStruct(value: 1, anotherValue: 2)

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

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

for v in 0..<iterations {
    aClass = aClass.setValue(UInt8(v % 255))
}
let classDuration = Date().timeIntervalSince(structStartDate)
print("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 = Date()
var complexStruct = ComplexStruct(values: [1])

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

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

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

simple struct 0.0083010196685791
simple class 0.0205469131469727
complex struct 0.0083010196685791
complex class 0.0205469131469727