内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

yizhihongxing

本文主要研究Tagged Pointer技术,针对该技术需要解决的问题、以及在实际应用中的价值做一些简单的探讨。

如果你想要更进一步,去挖掘Tagged Pointer是如何实现的,可以参考Friday Q&A 2012-07-27: Let's Build Tagged Pointersobjc源码

另外,本文中涉及到的示例代码,请在真机iOS设备上测试,因为Tagged Pointer技术针对不同的平台,具体实现细节是有差异的,否则无法得出和本文一致的测试结果。

一、对象的内存

下面我们针对iOS中对象进行一些探究,代码如下,其完整代码见TaggedPointer


    __weak NSNumber *weakNumber;
    __weak NSString *weakString;
    __weak NSDate *weakDate;
    __weak NSObject *weakObj;
    int num = 123;
    
    @autoreleasepool {
        weakObj = [[NSObject alloc] init];
        weakNumber = [NSNumber numberWithInt:num];
        weakString = [NSString stringWithFormat:@"string%d", num];
        weakDate   = [NSDate dateWithTimeIntervalSince1970:0];
    }
    NSLog(@"weakObj is %@", weakObj);
    NSLog(@"weakNumber is %@", weakNumber);
    NSLog(@"weakString is %@", weakString);
    NSLog(@"weakDate is %@", weakDate);

第7行,首先定义了4个__weak***对象,构建了一个autoreleasepool,所以在12行之后,所有__weak修饰的弱引用对象,都会被释放。经过上面分析,我们得出,对象会打印出null

但是,实际上,我们得到了如下的输出。

TaggedPointer[3570:3928309] weakObj is (null)

TaggedPointer[3570:3928309] weakNumber is 123

TaggedPointer[3570:3928309] weakString is string123

TaggedPointer[3570:3928309] weakDate is Thu Jan  1 08:00:00 1970

可以看到,只有NSObject对应的对象值是null,其他的值,均正常打印。

这是因为NSNumberNSStringNSDate,在这里采用了Tagged Pointer技术。

二、Tagged Pointer

2.1 Tagged Pointer技术

2.1.1 简介

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

2.2.2 未引入Tagged Pointer

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

2.2.3 引入Tagged Pointer

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

2.2.4 判断是否是Tagged Pointer

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

2.2 应用

2.2.1 支持的对象类型

可以从objc源码中找出支持Tagged Pointer 的对象类型,如下:


typedef uint16_t objc_tag_index_t;
enum
{
    OBJC_TAG_NSString          = 2, 
    OBJC_TAG_NSNumber          = 3, 
    OBJC_TAG_NSIndexPath       = 4, 
    OBJC_TAG_NSDate            = 6, 
    ....
};

即针对NSStringNSNumberNSDateNSIndexPath这些类型,都支持Tagged Pointer技术。

2.2.2 NSNumber

我们通过NSNumber以及NSString对象来观察Tag+Data的存储形式。

示例代码参见:TaggedPointer

如下所示,我们创建了很多NSNumber对象:

    NSNumber *number1 = @1;                          //0xb000000000000012
    NSNumber *number2 = @2;                          //0xb000000000000022
    NSNumber *number3 = @(0xFFFFFFFFFFFFFFF);        //0x1c0022560
    NSNumber *number4 = @(1.2);                      //0x1c0024b80
    int num4 = 5;
    NSNumber *number5 = @(num4);                     //0xb000000000000052
    long num5 = 6;
    NSNumber *number6 = @(num5);                     //0xb000000000000063
    float num6 = 7;
    NSNumber *number7 = @(num6);                     //0xb000000000000074
    double num7 = 8;
    NSNumber *number8 = @(num7);                     //0xb000000000000085
    
    //值:0xb000000000000012 0xb000000000000022 0x1c0022560 0x1c0024b80 0xb000000000000052 0xb000000000000063 0xb000000000000074 0xb000000000000085
    NSLog(@"%p %p %p %p %p %p %p %p", number1, number2, number3, number4, number5, number6, number7, number8);

由上表我们得出:

  • 很大的数字,超过Tagged Pointer表示上限的时候,将会转为对象存储,存放在堆上;
  • 如果是含有小数点的浮点数,将会直接以对象方式存储;
  • 其余类型的数字,包括不含小数部分的浮点型和整型都会以Tagged Pointer存储。

并且,针对以上部分,我们整理出Tagged Pointer的存储格式如下,以number1为例:

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

2.2.3 NSString

同上面NSNumber的处理逻辑,NSString处理的类似。


NSString *str1 = @"a";                                          //0x1049cc248
NSString *str2 = [NSString stringWithFormat:@"a"];              //0xa000000000000611
NSString *str3 = [NSString stringWithFormat:@"bccd"];           //0xa000000646363624
NSString *str4 = [NSString stringWithFormat:@"c"];              //0xa000000000000631
NSString *str5 = [NSString stringWithFormat:@"cdasjkfsdljfiwejdsjdlajfl"];//0x1c02418f0
NSLog(@"%@ %@ %@ %@ %@",
      [str1 class],   //__NSCFConstantString
      [str2 class],   //NSTaggedPointerString
      [str3 class],   //NSTaggedPointerString
      [str4 class],   //NSTaggedPointerString
      [str5 class]);  // __NSCFString

根据以上结果,我们将NSString分类三类:

  • 常量类型:__NSCFConstantString,定义的字符串常量。
  • Tagged Pointer类型:NSTaggedPointerString,通过对象方法创建的短字符串。
  • NSString对象类型:__NSCFString,包括NSString、NSMutableString等创建的字符串对象。

以上,整理如下:

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

NSString以Tagged Pointer的存储格式如下:

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

2.3 内存管理

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

三、一个面试问题的研究

该面试题如下:

内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用

参考

链接

1Friday Q&A 2012-07-27: Let's Build Tagged Pointers
2Tagged Pointer wiki
3NSString retain count -1
4objc源码

示例代码

1TaggedPointer

青山不改,绿水常流!谢谢大家支持。

原文链接:https://www.cnblogs.com/mysweetAngleBaby/p/16535444.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:内存管理(二)之别小看了Tagged-Pointer关键时刻起到大作用 - Python技术站

(0)
上一篇 2023年4月18日
下一篇 2023年4月18日

相关文章

  • Appuploader 常见错误及解决方法

    问题解决秘籍 遇到问题,第一个请登录苹果开发者官网 检查一遍账号是否有权限,是否被停用,是否过期,是否有协议需要同意,并且在右上角切换账号后检查所有关联的账号是否工作正常,apple账号的邮箱也是个重要的地方,当有ipa上传,账号有发生变化,被停用,apple经常发送一些邮件,去检查邮件通知,根据邮件通知修改调整。只有账号正常没问题,再考虑是否软件哪个地方操…

    IOS 2023年4月18日
    00
  • Uniapp进行APP打包——iOS 系统

    一、打包过程 1、创建唯一标识符 首先,申请苹果开发者账号。 没有苹果开发者账号是无法进行 ios 打包上线的。 (2) 进入 https://developer.apple.com 这个网址,点击“account” 并输入苹果开发者账号进入用户界面。 ​   (3) 点击证书文件 ​   (4) 进入到这界面以后, 点击“APP IDs”,并新建一个 AP…

    IOS 2023年4月18日
    00
  • 基于AVFoundation实现视频录制的两种方式

    目录 一、前言 二、方案一:AVCaptureSession + AVCaptureMovieFileOutput 1.创建AVCaptureSession 2.设置音频、视频输入 3.设置文件输出源 4.添加视频预览层 5. 开始采集 6. 开始录制 7.停止录制 8.停止采集 三、方案二:AVCaptureSession + AVAssetWriter …

    IOS 2023年4月18日
    00
  • 京喜APP – 图片库优化

    作者:京东零售 何骁 介绍 京喜APP早期开发主要是快速原生化迭代替代原有H5,提高用户体验,在这期间也积累了不少性能问题。之后我们开始进行一些性能优化相关的工作,本文主要是介绍京喜图片库相关优化策略以及关于图片相关的一些关联知识。 图片性能问题 作为电商APP,图片在各个业务场景被大量使用。我们需要做到尽可能降低网络消耗/内存消耗/硬盘消耗,同时不降低图片…

    IOS 2023年5月11日
    00
  • iOS 组件化实施过程

    目录 一、组件化的优缺点 二、组件化的拆分 三、组件与组件之间如何进行通讯(路由) 四、从Cocopods拉取代码的过程 五、创建本地私有库 一、组件化的优缺点 二、组件化的拆分 三、组件与组件之间如何进行通讯(路由) 四、从Cocopods拉取代码的过程 远程索引库里很多的.spec文件,该文件记录了很多内容,如用户名,框架名称,描述,框架的地址 Podf…

    IOS 2023年4月18日
    00
  • iOS的Runtime知识点繁杂难啃,真的理解它的思想,你就豁然开朗了

    一、Runtime 1、概念: 概念:Runtime是Objective-c语言动态的核心,即运行时。在面向对象的基础上增加了动态运行,达到很多在编译时确定方法推迟到了运行时,从而达到动态修改、确定、交换。。。属性及方法 作用: 这给程序员写代码带来很大的灵活性,比如说你可以把消息转发给你想要的对象,或者随意交换一个方法的实现之类的!多态 kvo kvc 获…

    IOS 2023年4月18日
    00
  • 中心化决议管理——云端分析

    作者:钱佳卫,研发工程师,产品研发和工程架构部-Client Infrastructure-App Infra-DevOps-Developer Tools 前言 CocoaPods 云端分析能力是字节跳动的终端技术团队(Client Infrastructure) 下 Developer Tools 部门提供的一系列云化基础设施之一, Developer …

    IOS 2023年4月18日
    00
  • 本文相关主要记录一下使用Hbuilder打包成苹果IOS-App的详细步骤。

    ​介绍一下个人开发者账号: 再说下什么是免费的苹果开发者账号,就是你没交688年费的就是免费账号,如果你想变成付费开发者账号,提交申请付费就行,账号都是一样的账号。 没有账号的点击链接申请: 苹果开发者账号申请 登录开发者中心developer.apple.com/account这个界面就是免费开发者账号 ​ 苹果免费开发者账号的功能限制 1、证书描述文件有…

    IOS 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部