iOS tagged pointer

释放双眼,带上耳机,听听看~!

iOS tagged pointer

从 64bit 开始,苹果引入了 tagged pointer 计数,用于优化 NSNumber , NSDate , NSString 等小对象的存储,没有这个数据之前,NSNumber 等对象需要动态分配内存,维护引用计数,NSNumber 指针存储的是堆中NSNumber对象的地址值,而引入了这个计数之后,NSNumber 指针里面存储的数据是 : tag + data ,也就是直接将数据存储在指针中。这样做特别节省空间。如果这个数据特别大,指针存储不下这个数,那么会回复之前的方式,存储在堆区,然后指针存放堆区的地址。

dispatch_queue_t queue = dispatch_get_global_queue(0, 0 );
    for (int i = 0 ; i < 10000; i ++) {
        dispatch_async(queue, ^{
            self.name = [NSString stringWithFormat:@"%@",@"123sdfasfdas"];
        });
    }

上面会发生什么呢?答案是可能崩溃,因为我们是多线程同时方位name的set方法,那么的set方法好比

-(void)setName:(NSString *)name{
    if (_name != name) {
        [_name release];
        _name = [name copy];
    }
}

好比这样,多个线程有可能同时去 release,所以会崩溃

解决方案,可以加锁,在name设置前后去加锁。

如果改成这样呢?

dispatch_queue_t queue = dispatch_get_global_queue(0, 0 );
    for (int i = 0 ; i < 10000; i ++) {
        dispatch_async(queue, ^{
            self.name = [NSString stringWithFormat:@"%@",@"123"];
        });
    }
    

就是把一个长字符串变成一个短的字符创,这时候发现,没有崩溃。因为后一个指针为 tagged pointer 类型的,就不存在release的操作,值直接就存储再来指针的里面,直接取值就可以了,所以就不会崩溃,他就不是一个OC对象。

 NSString *str = [NSString stringWithFormat:@"123"];
    NSString *str1 = [NSString stringWithFormat:@"aefasfasdfasfdasf"];
    NSLog(@"%@  %@",[str class],[str1 class]);


我们来打印下两个类

 NSTaggedPointerString  __NSCFString

可以看到 第一个类为 tagged pointer 类,也证明了我们的猜想。

其实源码里面是有判断的,当为mac 的时候 &1,当为ios的时候&(1<<63),所以 ios 最高有效位为1就为 tagged pointer 类型,mac 最低有效位为1就为tagged pointer

人已赞赏
iOS文章

iOS点击按钮放大后缩小效果

2020-5-18 21:33:02

iOS文章

iOS ,内存分布、内存管理 、isa 指针,散列表(引用计数表,弱引用表)

2020-5-18 22:48:02

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索