Memory & Performance
Swift manages object memory with ARC — Automatic Reference Counting: the compiler inserts retain/release calls at compile time, counts each object's owners, and frees it the instant that count hits zero. This is not a tracing garbage collector — there is no background scan and no unpredictable pause, so deinit runs deterministically. Grasping that single distinction separates the engineer who confidently hunts a leak from the one who repeats myths about "Swift's collector running under memory pressure".
The topic splits in two. First the memory model: how ARC counts owners, what strong, weak, and unowned each mean, how a retain cycle forms when two objects — or a closure and its self — hold each other strongly, and how a capture list breaks it. Then performance: why value semantics plus copy-on-write make struct copies cheap, where reference types spend heap and ARC traffic, when dispatch is dynamic versus static, and how you profile real work with Instruments instead of guessing.
Topic map
- Memory & ARC — compile-time reference counting,
strong/weak/unowned, retain cycles from mutual references and capturedself, breaking them with[weak self],deinittiming, and why value types need no ARC. - Performance — value semantics and copy-on-write, stack versus heap and the cost of reference types, static versus dynamic dispatch, measuring with Time Profiler / Allocations / Leaks, and the main-thread traps that drop frames.
Common traps
| Mistake | Consequence |
|---|---|
| Thinking ARC scans the heap like a garbage collector | Wrong mental model of when and how objects are freed |
Swapping weak and unowned — believing weak crashes | An unowned reference read after dealloc is undefined behavior |
| Expecting ARC to detect and break retain cycles | Two objects strongly referencing each other leak forever |
| Assuming a struct is always cheap to copy and stack-allocated | A captured or boxed struct is heap-allocated; large structs cost |
| Guessing at the hot path instead of profiling | You optimize code that was never the bottleneck |
| Decoding images or parsing JSON on the main thread | The frame budget is blown and scrolling drops frames |
Interview relevance
Memory and performance are asked to test whether you understand the machine or recite marketing. A candidate who says "ARC inserts retain/release at compile time and frees at count zero, so freeing is deterministic" immediately gets ahead of one who calls it "Swift's garbage collector".
Typical checks:
- What ARC is and how it differs from a tracing collector.
- The difference between
weak(optional, auto-zeroed) andunowned(non-optional, crashes after dealloc). - How a retain cycle forms — mutual references or a closure capturing
self— and how to break it. - Why value types are cheap under copy-on-write and where reference types spend heap and ARC.
- How you prove a leak or a hang with Instruments rather than guessing.
Common wrong answer: "Swift has a garbage collector that frees objects when memory runs low." In reality ARC is compile-time reference counting with deterministic, pause-free deallocation — the exact opposite of the nondeterministic timing a collector gives you.