美文网首页
TaggedPointer

TaggedPointer

作者: 0胡杨0 | 来源:发表于2020-06-08 13:10 被阅读0次

    TaggedPointer特点:

    1,Tagged Pointer专门用来存储小的对象,例如NSNumber和NSDate, 当然NSString小于10字节的也可以运用了该手段(但是汉字除外,原因不明).
    2,Tagged Pointer指针的值不再是地址了,而是真正的值。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已,因为他没有isa指针。所以,它的内存并不存储在堆中,也不需要malloc和free。
    3, 在内存读取上有着3倍的效率,创建时比以前快106倍。

    理解:

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

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


    image.png

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

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

    所以我们可以将一个对象的指针拆成两部分,一部分直接保存数据,另一部分作为特殊标记,表示这是一个特别的指针,不指向任何一个地址。所以,引入了Tagged Pointer对象之后,64位CPU下NSNumber的内存图变成了以下这样:


    image.png

    当8字节可以承载用于表示的数值时,系统就会以Tagged Pointer的方式生成指针,如果8字节承载不了时,则又用以前的方式来生成普通的指针。

    Tagged Pointer的引入也带来了问题,因为它并不是真正的对象,而是一个伪对象,所以你如果完全把它当成对象来使,可能会让它露出马脚.
    因为不是真正的对象,所以如果你直接访问Tagged Pointer的isa成员的话,会在编译的时出现警告。只要避免在代码中直接访问对象的 isa 变量,即可避免这个问题。
    ps:内容参考自唐巧大神《深入理解Tagged Pointe》

    相关文章

      网友评论

          本文标题:TaggedPointer

          本文链接:https://www.haomeiwen.com/subject/bqbltktx.html