美文网首页
Tagged Pointer 和 nonpointer

Tagged Pointer 和 nonpointer

作者: 梦里桃花舞倾城 | 来源:发表于2020-06-08 18:04 被阅读0次

    前言

    20139 月,苹果推出了 iPhone5s,与此同时,iPhone5s 配备了首个采用 64 位架构的 A7双核处理器,为了节省内存和提高执行效率,苹果提出了Tagged Pointer的概念。对于 64 位程序,引入 Tagged Pointer 后,相关逻辑能减少一半的内存占用,以及3 倍的访问速度提升,100倍的创建、销毁速度提升。

    问题

    我们先看看原有的对象为什么会浪费内存?

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

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

    01

    Tagged Pointer

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

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

    02
    • Tagged Pointer是专⻔⽤来存储⼩的对象,例如NSNumber,NSDate等。
    • Tagged Pointer指针的值不再是地址了,⽽是真正的值。所以,实际上它不再是⼀个对象了,它只是⼀个披着对象⽪的普通变量⽽已。所以,它的内存并不存储在堆中,也不需要mallocfree
    • 当指针不够存储数据时,就会使用动态分配内存的方式来存储数据。
    • 在内存读取上有着3倍的效率,创建时⽐以前快106倍。

    总结

    苹果将Tagged Pointer引入,给64位系统带来了内存的节省和运行效率的提高。Tagged Pointer通过在其最后一个 bit 位设置一个特殊标记,用于将数据直接保存在指针本身中。因为Tagged Pointer并不是真正的对象。

    nonpointer

    isa

    nonpointer

    • 0,代表普通的指针,存储着ClassMeta-Class对象的内存地址
    • 1,代表优化过,使用位域存储更多的信息

    has_assoc

    • 是否有设置过关联对象,如果没有,释放时会更快

    has_cxx_dtor

    • 是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快

    shiftcls

    • 存储着ClassMeta-Class对象的内存地址信息

    magic

    • 用于在调试时分辨对象是否未完成初始化

    weakly_referenced

    • 是否有被弱引用指向过,如果没有,释放时会更快

    deallocating

    • 对象是否正在释放

    extra_rc

    • 里面存储的值是引用计数器减1

    has_sidetable_rc

    • 引用计数器是否过大无法存储在isa
    • 如果为1,那么引用计数会存储在一个叫SideTable的类的属性中

    参考链接:巧神:
    深入理解Tagged Pointer

    相关文章

      网友评论

          本文标题:Tagged Pointer 和 nonpointer

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