Tagged Pointer这东西你知道吗?

Tagged Pointer 作用是什么?

为了改进从 32位CPU 迁移到 64位CPU 的内存浪费和效率问题,在 64位CPU 环境下,引入了 Tagged Pointer 对象。有了这样的机制,系统会对 NSStringNSNumberNSDate等对象进行优化。

原有的对象为什么会浪费内存呢?

假设我们要存储一个 NSNumber 对象,其值是一个整数。正常情况下,如果这个整数只是一个 NSInteger 的普通变量,那么它所占用的内存是与 CPU 的位数有关,在 32 位 CPU 下占 4个字节,在 64 位 CPU 下是占8个字节的。而指针类型的大小通常也是与 CPU 位数相关的,一个指针所占用的内存在 32 位 CPU 下为 4 个字节,在 64 位 CPU 下也是 8 个字节。

所以一个普通的 iOS 程序,如果没有 Tagged Pointer 对象,从 32 位机器迁移到 64 位机器中后,虽然逻辑没有任何变化,但这种 NSNumberNSDate 一类的对象所占用的内存会翻倍。

taggedpointer.png

效率问题

从效率上来看,为了存储和访问一个 NSNumber 对象,我们需要在堆上为其分配内存,另外还要维护它的引用计数,管理它的生命周期。这些都给程序增加了额外的逻辑,造成了运行效率上的损失。

所以为了改进上面提到的内存占用和效率问题,苹果提出了 Tagged Pointer 对象,由于 NSNumberNSDate 一类的变量本身的值需要占用的内存大小常常不需要 8 个字节,拿整数来说,4 个字节所能表示的有符号整数就可以达到 20 多亿(2 ^ 31 = 2147483648,另外 1 位作为符号位),对于绝大多数情况都是可以处理的。

所以它将一个对象的指针拆分成两部分,一部分直接保存数据,另一部分作为特殊标记,表示这是一个特别的指针,不指向任何一个地址

Tagged Pointer 特点:
  • Tagged Pointer 专门用来存储小的对象,例如 NSNumberNSDate
  • Tagged Pointer 指针的值不再是地址了,而是真正的值。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已。所以,它的内存并不存储在堆中。
  • 在内存读取上有着 3 倍的效率,创建时比以前快 106

还有一点,注意⚠️
所有对象都有 isa 指针,而Tagged Pointer其实是没有的,因为它不是真正的对象。因为不是真正的对象,所以如果你直接访问Tagged Pointer的isa成员的话,编译时将会有如下警告。应该换成相应的方法调用,如 isKindOfClass 和 object_getClass。只要避免在代码中直接访问对象的 isa 变量,即可避免这个问题。

参考文章

深入理解Tagged Pointer
Objective-C对象的TaggedPointer特性

你可能感兴趣的:(Tagged Pointer这东西你知道吗?)