Swift弱引用管理之Side Table

Swift弱引用管理之Side Table_第1张图片
Photo by Content Pixie

Side Table的引入是Swift弱引用管理系统中的一个明智改进,它最早出现在Swift 4中。

让我们仔细研究一下Side Table的概念以及它解决了哪些问题。

Swift引用计数 - 核心概念

  • 强引用对象会持有这个实例,并且只要强引用仍然存在,就不允许对其进行释放。
  • 弱引用是一种引用,它不会持有所引用的实例,因此也不会阻止ARC销毁所引用的实例。
  • Unowned引用方式也是弱引用的一种。 区别是访问计数器为零的引用会导致运行时错误。 当另一个实例的寿命相同或更长时,可以使用它。

同样值得注意的是,Swift中的对象有三种计数器:强引用,弱引用和无主引用。 这些计数器存储在isa之后或者存储在Side table中,稍后将对其进行说明。

除此之外,弱引用和无主引用的计数器比强引用多+1。 当对象执行完析构和销毁内存后,这个附加值将减小。 为了使本文简单,我将使用0作为两种类型引用的起点。

Swift4之前的弱引用管理

为了演示旧引用计数的工作原理,让我们从一个示例入手。

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

这是一个带有两个属性的User类。 下面的图片表示对象在内存中的表示。

Swift弱引用管理之Side Table_第2张图片
image

类,属性和引用计数器是内联存储的。 它比将数据存储在外部内存块中要快一些。

假设有一个弱引用 引用了这个User,并且一段时间后,强计数器变为了零,而弱计数器仍然不为零。

Swift弱引用管理之Side Table_第3张图片
layout2

在这种情况下,自动引用计数将会把该对象从内存
中删除。 尽管这样会导致对象销毁,但不会释放其内存。

当另一个对象通过弱引用访问被销毁的对象时,弱计数器将减少。 当弱计数器达到零时,将最终释放内存。 这意味着我们的User成为可能长时间占用内存的僵尸对象。

Swift 的 Side Table

Side Table是一个单独的内存块,用于存储对象的其他信息。 现在它只存储了计数器和flags。

Swift弱引用管理之Side Table_第4张图片
layout3

该对象最初是没有Side Table的,在以下情况下会自动创建:

  • 对象由弱引用指向时
  • strongunowned 计数器溢出(在32位系统上,嵌入式计数器很小)。

对象和Side Table都具有指向彼此的指针。 获取Side Table是一种单向操作。

另一件需要引起注意的事,“弱”引用现在直接指向Side Table,而“强”和“无主”引用仍然直接指向对象。 这样就可以完全释放对象的内存

Swift弱引用管理之Side Table_第5张图片
layout4

总结

Side Table 为原来的引用计数带来了明显的改进:

  • 首先,它允许弱引用指向的对象按时释放而不会存在僵尸对象。
  • 其次,它可能会在将来的发行版中为扩展其他存储属性打开大门。

推荐阅读

  • Apple Swift Book — Automatic Reference Counting https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html#ID52
  • Swift Source Code — RefCount.h https://github.com/apple/swift/blob/d1c87f3c936c41418ee93320e42d523b3f51b6df/stdlib/public/SwiftShims/RefCount.h#L44
  • 阿里大牛从源码解析弱引用 https://juejin.im/post/5c7b835af265da2d881b4457

作者:Maxim Eremenko

翻译:乐Coding


更多Swift文章和iOS开发技术请关注公众账号:乐Coding。建了个【Swift开发】微信交流群,欢迎加入。

Swift弱引用管理之Side Table_第6张图片
微信群

你可能感兴趣的:(Swift弱引用管理之Side Table)