The Side Table is a sensible improvement for the reference management system, firstly introduced in Swift 4.

Let’s take a closer look at this concept and which problems it solves in the existing approach.

Core Concepts of Swift Reference Management

  • Strong reference keeps a firm hold on the instance and does not allow it to be deallocated for as long as that strong reference remains.

  • Weak reference is a reference that does not keep a strong hold on the instance it refers to, and so does not stop ARC from disposing of the referenced instance.

  • Unowned reference as a weak one does not keep a strong hold. Access to unowned references with a zero counter leads to runtime errors. Use it when the other instance has the same or a longer lifetime.

It’s also worth noting that objects in Swift conceptually have several counters: for strong, weak, and unowned references. These counters are stored either inline right after the isa or in a side table, which will be explained a bit later.

Besides this, weak and unowned counters have an extra +1 from strong references. The additional value is decremented after the object’s deallocation and deinitialization, respectively. For the simplicity of the article, I will use 0 as a starting point for both types of references.

Weak References Before Swift 4

To demonstrate how the old approach works, let’s consider an example first.

class User {
    let id: Int
    let email: String
}

Here is a User class with two properties. The next picture represents this object in memory.

The class, properties, and reference counters are stored inline. It allows somewhat faster access than storing the data in the external chunk of memory.

Let’s suppose a User is referred by one weak reference, and after some time, a strong counter comes to zero while the weak count is still non-zero.

In this situation, the object is intended to be deleted from memory by Automatic Reference Counting. Despite this fact causes the object’s deinitialization, its memory is not deallocated.

The weak counter is decremented when another object accesses the destroyed one by a weak reference. When a weak counter reaches zero, memory is finally deallocated. It means that our user becomes a zombie object that may occupy memory for a long time.

Understanding Swift Side Tables

The Side Table is a separate chunk of memory which stores additional object’s information. Currently, it stores reference counters and flags.

The object initially has no Side Table, and it’s automatically created when:

  • the object is pointed by a weak reference.
  • strong or unowned counter overflows (an inlined counter is small on a 32-bit system).

Both the object and side table have a pointer to each other. Gaining a Side Table is a one-way operation.

Another thing to draw the attention is that weak references now point directly to the Side Table, whereas strong and unowned ones still point directly to the object. This allows the object’s memory to be fully deallocated.

Wrapping Up

The Side Table brings a tangible improvement for the existing approach:

  • First of all, it allows objects pointed by weak references to be fully deallocated on time.
  • Moreover, it may open the door for stored properties in extensions in the future releases.

External Resources

Further Reading

I highly recommend to get familiar with this article:

By the way, let’s be friends on Twitter.