In Swift worden value types, zoals struct, enum en tuple, meestal op de stack geplaatst, terwijl reference types, zoals class, op de heap worden geplaatst.
Stack allocation is snel, automatisch en wordt gebruikt voor het opslaan van lokale variabelen met een korte levensduur. Heap allocation vereist extra kosten en wordt gebruikt voor objecten met een onbepaalde levensduur of grootte.
Voorbeeld:
struct Point { var x: Int; var y: Int } let p1 = Point(x: 2, y: 3) // Op de stack class Node { var value: Int; init(value: Int) { self.value = value } } let n1 = Node(value: 5) // Op de heap
Nuances:
Prestaties: Stack allocation is sneller, omdat het geen geheugenverwerking op de heap en levensduurbeheer van objecten vereist.
Worden alle structuren (struct) altijd uitsluitend op de stack geplaatst?
Antwoord:
Nee! Hoewel structuren value types zijn en vaak op de stack worden geplaatst, kan de compiler ze op de heap opslaan als ze zich binnen een class-object, array, dictionary bevinden of worden gebruikt als captured value in een closure. Bijvoorbeeld:
class Box { var point: Point init(point: Point) { self.point = point } } let box = Box(point: Point(x: 1, y: 2))
Hier wordt het exemplaar Point op de heap opgeslagen, omdat het toebehoort aan de class Box.
Verhaal
Een ontwikkelaar probeerde de prestaties van structuren te optimaliseren, denkend dat grote structuren altijd op de stack zouden liggen, en hield geen rekening met het feit dat collecties (Array, Dictionary) heap allocation gebruiken, wat leidde tot onverwachte toename van geheugenverbruik in het project.
Verhaal
In het project werd niet overwogen dat een closure de waarde van een structuur capteert, die op de heap komt te liggen, wat invloed heeft op de levensduur van het object. Dit verhoogde de levensduur van de variabelen en leidde tot geheugenlekken, aangezien men auto-ontlasting bij het verlaten van de scope verwachtte.
Verhaal
Het gebruik van arrays met zware structuren zonder het begrijpen van copy-on-write leidde tot onverwacht dure kopieerbewerkingen door het doorgeven van collecties tussen threads, wat de prestaties verlaagde en vertragingen in de UI veroorzaakte.