What actually allocates on the heap in Swift, and how do you see it?
Predict first
What does this print, in bytes?
print(MemoryLayout<() -> Void>.size, MemoryLayout<String>.size)
- 8 8
- 16 16
- 8 24
Mental model. A value is a note kept in your pocket. A heap object is a locker you rent: costly to open, and everyone with the key has to be tracked.
Structs, enums and tuples are stored inline where they live (in a stack frame, in another object, in an array’s buffer) and need no allocation of their own. The heap is used for: class instances; the buffers of arrays, dictionaries, sets and long strings; closure contexts and boxes for variables captured by an escaping closure; existential boxes for values bigger than three words; indirect enum payloads; and the frames of async work. A small non-escaping closure and a small string (up to 15 UTF-8 bytes, stored inside the 16-byte String) need none.
The optimiser can promote some allocations to the stack when it can prove they do not escape, so reading source is not enough. Measure: the Allocations instrument shows each allocation and its call stack, and a breakpoint on swift_allocObject catches class allocations. Reduce allocations in hot paths by using value types, reserving capacity, avoiding existentials in tight loops, and not creating closures per iteration.
A closure value is a function pointer plus a context pointer; a String is 16 bytes and stores short text inline without allocating.
Common traps
- “Structs never touch the heap.” A struct that holds an array or class reference points into the heap; the struct itself may be boxed when captured or existential.
- Guessing instead of measuring. Stack promotion and inlining change the answer between Debug and Release.
They might follow up with
- Where do the three-word existential and the stack/heap story appear? In the Types section: stack-or-heap and existential container questions.
- What does a closure value cost? Two words: a function pointer and a context pointer. The context is heap-allocated only if it captures something.
Related questions
- 1.1.3 Where do value types live — stack or heap?
- 1.4.6 What is an existential container? What is a witness table?
- 3.4.1 What does a class instance look like in memory?
← What do MemoryLayout’s size, stride and alignment mean, and why does… What is a side table, and when does the runtime create one? →