iOS-内存管理-布局与方案

一、内存布局

二、内存管理方案

1. TaggedPointer

对于小对象比如NSNumber,采用这种方案。

2. NONPOINTER_ISA

在64位架构下的isa指针是64bit位,实际上33位就能够表示类对象(或元类对象)的地址,为了提供内存的利用率,在剩余的bit位当中添加了内存管理的数据内容。

NONPOINTER_ISA64位中各位的功能

NONPOINTER_ISA64位中各位的功能

主要位的介绍:
1.第一位index位,表示该isa指针是否是NONPOINTER_ISA指针。如果是0表示为pointer类型的指针,即该指针的64位值表示的就是类对象的地址。
2.第二位has_assoc,表示是否有assoc关联对象。
3.shiftcls一共33位,表示类对象的内存地址。
4.weakly_referenced位,表示该对象是否有弱引用指针。
5.最后的extra_rc位,可以存储引用计数,如果引用计数的值很小,则通过它来存储,如果超过了它范围,则会通过sidetables引用技术标来存储
6.has_sidetable_rc位,表示是否有散列表。

3. 散列表SideTables()

3.1 SideTables()

SideTables()实际是一个哈希表,我们可以通过对象指针,找到所对应的引用计数表或弱引用表位于哪个SideTable表中。也就是有多个sideTable表。

知识点1:为什么不是一个大表,而是多个表?
回答:如果只有一张表,所有对象的引用计数都放到一张表中,则如果在修改某个对象的引用计数的时候,由于对象可能在不同线程中被操作,则需要对表进行加锁,这样一来,效率就会极地。
知识点2:什么是哈希表

通过hash函数可以快速通过key值,得到所对应的数组当中的索引位置。赋值和获取都避免了遍历,提高了效率。

3.2 SideTable结构


我们可以看到,SideTable是有三部分组成:

3.2.1 Spinlock_t自旋锁
  • 是一种“忙等”的锁,如果锁已被其他线程获取,则当前线程会不断探测锁,如果探测到锁被释放,则获取锁。
  • 适用于轻量访问。比如引用计数的修改。
3.2.2 引用计数表

引用计数表也是一个hash表,通过hash函数找到指针对应的引用计数的位置。

下面来看size_t的具体内容:


3.2.3 弱引用表

弱引用表也是一个hash表,通过hash函数找到对象对应的弱引用数组。

推荐阅读更多精彩内容