1.前言
在学习ARC机制的时候,在retain代码中
- (id)retain {
return ((id)self)->rootRetain();
}
inline id objc_object::rootRetain()
{
if (isTaggedPointer()) return (id)this;
return sidetable_retain();
}
看到了如下的代码
if (isTaggedPointer()) return (id)this;
首先会判断是否是Tagged Pointer,是的话将不做处理,那么就很好奇这个神秘的指针了。
2.NSNumber中的TaggedPointer
Tagged Pointer是一个能够提升性能、节省内存的有趣的技术,苹果公司基于这两方面考量推出了这一技术。
一般来说,64位机器在没有Tagged Pointer技术的情况下
NSNumber * test = @1;
将有两部分内存占用,一个是储存‘1’的NSNumber对象,储存一个NSInteger数值8字节,一个是NSNumber指针8字节。这样来说将会出现16字节的内存占用。但是很显然大部分情况下,我们常见的整型值用四个字节都基本够用了。在处理NSNumber时便是如此,我们运行以下代码时
NSNumber * test = @1;
NSLog(@"NSp is %p ,%@",test ,test);
test = @2;
NSLog(@"NSp is %p ,%@",test ,test);
test = @(0xCFFFFFFFFFFFFFFF);
NSLog(@"NSp is %p ,%@",test ,test);
控制台输出如下
2018-03-29 20:33:00.052755+0800 CLASS1[13338:596818] NSp is 0xb000000000000012 ,1
2018-03-29 20:33:00.054739+0800 CLASS1[13338:596818] NSp is 0xb000000000000022 ,2
2018-03-29 20:33:00.056193+0800 CLASS1[13338:596818] NSp is 0x6080000369c0 ,14987979559889010687
我们可以看到0xbxxxxxxxxxxx2的格式,这个时候我们大概可以做出一个推论,对于NSInteger数值,NSNumber指针中藏了自己的对象,只有接近或大于8字节能表示的值(明天有时间写个小程序测试下)时候才会真正地生成NSNumber对象,这一角度看这的确是很好的节省方法。
特点:
-
Tagged Pointer
专门用来存储小的对象,例如NSNumber
和NSDate
-
Tagged Pointer
指针的值不再是地址了,而是真正的值。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已。所以,它的内存并不存储在堆中,也不需要malloc和free。 - 在内存读取上有着3倍的效率,创建时比以前快106倍。
备注:在WWDC2013的《Session 404 Advanced in Objective-C》视频中介绍。
3.在NSString中的TaggedPointer
请看【采用Tagged Pointer的字符串】,翻译的很棒,原文【Friday Q&A 2015-07-31: Tagged Pointer Strings】
囫囵吞枣有空还要细读,无力拙劣复述了。
网友评论