在调试程序或者反编译App时,经常可以看到”NSTaggedPointerString”这个东西,经过查阅发现从64bit开始,iOS引入了Tagged Pointer技术,用于优化NSNumber、NSDate、NSString等小对象存储,在没有使用Tagged Pointer之前,NSNumber等对象需要动态分配内存、维护引用计数等,NSNumber指针存储的是堆中NSNumber对象的地址值.使用Tagged Pointer之后,NSNumber指针里面存储的数据变成了:存储数据+TaggedPoint标识,也就是将数据直接存储在了指针中,Tagged Pointer指针的值不再是地址了,而是真正的值。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已。所以,它的内存并不存储在堆中,也不需要malloc和free。在内存读取上有着3倍的效率,创建时比以前快106倍。不但减少了64位机器下程序的内存占用,还提高了运行效率。完美地解决了小内存对象在存储和访问效率上的问题。当指针不够存储数据时,才会使用动态分配内存的方式来存储数据.
我们对比一下,使用Tagged Pointer与否时内存布局:
没使用Tagged Pointer时

使用Tagged Pointer时

简单的说,在64位系统中,一个指针为8字节,当指针关联的值小于8位的时候,系统会将指针转化成Tagged Pointer,并在最后一个bit位加入TaggedPoint标识,这个指针的结构就变成了“0x存储数据+TaggedPoint标识”的结构。看下面的例子就能明白:
1 | |
可以看出取消最前面的0xb以及最后一位TaggedPoint标记2, 那么剩下的就是number1的值,正好是1.