2021-08-03

Tagged Pointer 技术

定义
Tagged pointer 是一项用于提高性能并减少内存使用的有趣技术。在 OS X 10.10 中,NSString 也开始使用了 tagged pointer 技术,今天我会在 Ken Ferry 的提议下,窥探其工作原理。

概述Tagged pointer原理

对象存储在内存中的时候是内存对齐的,因此他们的地址总是单个指针大小的倍数,在实际中通常是 16 的倍数。对象的指针通常是以一个完整的 64 位整型的结构进行存储,不过由于内存对齐的,指针中一些位总会为零。

Tagged pointer 技术受益于此,通过让这些位不再为 0,赋予了对象指针一些特殊意义。在苹果的 64 位 Objective-C 实现当中,对象指针的最低有效位设置为 1 的时候 (也就是说,它是一个奇数) ,此指针被认为是 tagged pointer。此时,最低有效位前面的 3 位不再被当作 isa 指针的地址,而是用于表示一个特殊的 tagged class 表的索引值。这个索引值可以用来查找 tagged pointer 所对应的类。剩余的 60 位则会被直接使用。

来看一个对上述理论的简单应用:当我们创建一个 NSNumber 对象时,如果它适合于 tagged pointer 技术,那么这个对象将不再是一个真正的 NSNumber 对象——它的指针会自动转换为 tagged pointer 指针,并且最低位会被设置为 1;接下来的 3 位会设为 NSNumber 所对应的 tagged class 在一个全局表中的索引;而剩余的 60 位会用作保存其数值 —— 比如一个能用 60 位表示的整型值。

对于外部而言,这样的一个指针与其他任何对象的指针看起来都是一样的。它能像其他对象一样响应消息,因为 objc_msgSend 知道它是一个 tagged pointer 类型的指针。假如你要向它发送 integerValue 的消息,OC 运行时会帮助我们从它存储数据的 60 位中拿出数据并返回。

尽管为了对外统一,运行时做了很多额外工作,但最终你节省了一次内存的初始化,一次指针的间接访问,并且也不会有任何关于引用计数的操作 —— 因为没有内存需要被释放。对于一些经常使用的类来说,这能带来显著的性能提升。

NSString如何应用tagged pointer 技术

NSString 看起来不太适用于 tagged pointer 技术,因为它的长度是可变的,而且可能会远远超出 tagged pointer 所能存储的范围。但话虽如此,一个 tagged pointer 的类是可以和普通的类共存的 —— 某些值使用 tagged pointer,另外一些值使用普通指针。例如,对于 NSNumber 来说,一个大于 2^60 - 1 的整型超出了 tagged pointer 所能存储的范围,那么它就需要存储为一个在内存中初始化的普通 NSNumber 对象。

NSString 亦是如此。假如某些字符串可以保存为 60 位以内的二进制数据,它会创建为 tagged pointer,而其他字符串会保存为普通的对象。据此我们可以假设,如果小的字符串经常被使用且达到一定的使用量时,它会获得可观的性能。在真实的代码中会有如此效果吗?显然苹果给出了肯定的答案 —— 如果没有实际效果,他们不会尝试去实现它。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值