Jacob’s Tech Tavern

Jacob’s Tech Tavern

Share this post

Jacob’s Tech Tavern
Jacob’s Tech Tavern
Bits & Side Tables: How Reference Counting Works in Swift

Bits & Side Tables: How Reference Counting Works in Swift

Deep under the hood of Swift's heap objects

Jacob Bartlett's avatar
Jacob Bartlett
Aug 25, 2025
∙ Paid
7

Share this post

Jacob’s Tech Tavern
Jacob’s Tech Tavern
Bits & Side Tables: How Reference Counting Works in Swift
1
Share

Every iOS dev has a soft spot, or perhaps a weak spot, for Swift reference counts. This stems from the fact that we've all survived countless interview questions about it:

  • For your first job, you’ll no doubt be asked the classic “what's the difference between a value type and a reference type?”

  • As you grow to mid-level, maybe you’ll be asked “how is a weak reference different from an unowned reference?”

  • Perhaps if you're ever interviewed by me (a sadist, and not the saucy 50 shades of grey kind), I’ll throw out “why was the side table introduced?”

Reference counting is fundamental to the Swift you write every day. By understanding how something really works, down to the bit level, you have the theoretical foundation to eviscerate any interview curveball I can lob at you.

So today, we’re spelunking again through the low-level guts of the Swift Runtime, to find out the answers to questions like:

  • Where are the bits that make up strong, weak, and unowned reference counts stored?

  • Why are weak references less performant than strong and unowned references?

  • How does an unowned reference crash if it's accessed after deallocation?

  • Are unowned references always more performant than weak references?

Once you’ve digested this article, you’ll be able to flip the interview table, and make me your bitch.

  • Quick primer on the Swift Runtime

  • Strong References & Bit Counting

    • HeapObject

    • Retaining a HeapObject

    • Every Bit Counts!*

    • Incrementing the RefCount

    • Slow Reference Counting

  • Weak References & Side Tables

    • Pre-Swift 4

    • The Side Table

    • Performance Penalty 1: Indirection and Cache Misses

    • Performance Penalty 2: Allocation and Atomic Operations

    • Performance Penalty 3: What do you mean strong refs are slower now?

    • Performance Recap

  • Unowned References & Crashes

    • Unowned Crashing

    • Unowned Performance #1: longer than you think, dad!

    • Unowned Performance #2: Zombies!? Again?!

    • The Object Lifecycle

  • Special Cases

    • unowned(unsafe)

    • Immortal Objects

    • Stack Promotion

  • Never Fail An Interview Again → (start here to quickly see the answers) ←

  • Last Orders

Subscribe to Jacob’s Tech Tavern for free to get ludicrously in-depth articles on iOS, Swift, tech, & indie projects in your inbox every week.

Paid members get several benefits:

  • Access Elite Hacks, my exclusive advanced content 🌟

  • Read my free articles a month before anyone else 🚀

  • Grow your career with my Swift Concurrency course 🧵

Upgrade to read this article right now, or wait until September 29.

This article is quite long, so your email client may cut it off. You’ll have a better experience reading it on your web browser.

Read on my website

Keep reading with a 7-day free trial

Subscribe to Jacob’s Tech Tavern to keep reading this post and get 7 days of free access to the full post archives.

Already a paid subscriber? Sign in
© 2025 Jacob Bartlett
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share