本文主要研究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 简介

2.2.2 未引入Tagged Pointer

2.2.3 引入Tagged Pointer

2.2.4 判断是否是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为例:

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等创建的字符串对象。

以上,整理如下:

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

2.3 内存管理

三、一个面试问题的研究

该面试题如下:

参考

链接

1Friday Q&A 2012-07-27: Let's Build Tagged Pointers

2Tagged Pointer wiki

3NSString retain count -1

4objc源码

示例代码

1TaggedPointer

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

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

  1. JVM内存管理(二)

    JVM内存管理          JVM在执行java程序的过程中,会把内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖 ...

  2. OC的内存管理(二)ARC

    指针: 指向内存的地址指针变量 存放地址的变量指针变量值 变量中存放的值(地址值)指针变量指向的内存单元值 内存地址指向的值1):强指针:默认的情况下,所有的指针都是强指针,关键字strong ):弱 ...

  3. Linux内存描述之内存节点node--Linux内存管理(二)

    1 内存节点node 1.1 为什么要用node来描述内存 这点前面是说的很明白了, NUMA结构下, 每个处理器CPU与一个本地内存直接相连, 而不同处理器之前则通过总线进行进一步的连接, 因此相对 ...

  4. Linux内存描述之内存节点node–Linux内存管理(二)

    日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDrivers Linux内存管理 #1 ...

  5. 高端内存映射之kmap_atomic固定映射--Linux内存管理(二十一)

    1 固定映射 1.1 数据结构 linux高端内存中的临时内存区为固定内存区的一部分, 对于固定内存在linux内核中有下面描述 x86 arm arm64 arch/x86/include/asm/ ...

  6. 高端内存映射之kmap持久内核映射--Linux内存管理(二十)

    1 高端内存与内核映射 尽管vmalloc函数族可用于从高端内存域向内核映射页帧(这些在内核空间中通常是无法直接看到的), 但这并不是这些函数的实际用途. 重要的是强调以下事实 : 内核提供了其他函数 ...

  7. linux2.6 内存管理——逻辑地址转换为线性地址(逻辑地址、线性地址、物理地址、虚拟地址)

    Linux系统中的物理存储空间和虚拟存储空间的地址范围分别都是从0x00000000到0xFFFFFFFF,共4GB,但物理存储空间与虚拟存储空间布局完全不同.Linux运行在虚拟存储空间,并负责把系 ...

  8. iOS学习之Object-C语言内存管理高级

    一.属性的内存管理

  9. cocos2d-x c++和object-c内存管理比较

    转自:http://www.2cto.com/kf/201307/227142.html 既然选择了C++作为游戏开发的语言, 手动的管理内存是难以避免的, 而Cocos2d-x的仿Objctive- ...

  10. (三)java虚拟机内存管理和线程独占区和线程共享区

    一.内存管理 二.线程独占区之程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里,字节 ...

随机推荐

  1. 在线安装gfortran的方法-CentOS8 or 阿里龙蜥

    在线安装gfortran的方法-CentOS8 or 阿里龙蜥 背景 在阿里云上面进行了 speccpu2006的测试验证 但是发现总是很多包安装不过去 原因是阿里最小化安装的龙蜥系统. 缺少很多编译 ...

  2. Oracle 高版本导出到低版本的测试验证

    今天验证Oracle 由高版本 备份恢复到低版本 与方神沟通(双 还是他) 说可以使用 version的参数..然后搞一下.. expdp system/Test6530@ora12cr2 schem ...

  3. CentOS8 的容器运行时解决中文乱码问题的一个思路

    首先说明一下 CentOS7和CentOS8关于locale语言文件的位置是不一样的. Docker pull centos 拉取下来的镜像 一般是不带中文语言包的. 简单方法是在 CentOS之后安 ...

  4. 从零开始匹配vim(0)——vimscript 简介

    通过之前一系列的文章,相信各位小伙伴应该已经对vim产生了浓厚的兴趣,可能不少小伙伴通过慢慢的使用变的跟我一样,离开vim就不会写代码了.如果你希望继续长时间使用vim,甚至将vim作为主要的代码编辑 ...

  5. Linux服务器Crontab定时任务配置

    1.检查linux系统是否有crontab rpm -qa | grep crontab 2.如果未安装进行安装 yum -y install vixie-cron yum -y install cr ...

  6. Linux--uniq 命令(检查和处理重复行的数据)

    文本中的重复行,基本上不是我们所要的,所以就要去除掉.linux下有其他命令可以去除重复行,但是我觉得uniq还是比较方便的一个. 使用uniq的时候要注意以下二点1.对文本操作时,它一般会和sort ...

  7. 华为云GaussDB支撑农行超级网银业务,性能和稳定性备受认可

    数据库作为数据驱动业务创新和智慧银行建设的关键基础设施,在银行数字化变革中具有举足轻重的作用. 在金融科技发展和国家政策引领下,银行纷纷加快推进数字化转型时代,正在经历一场以科技引领.数据赋能.数字经 ...

  8. JS Leetcode 74. 搜索二维矩阵题解分析,二分法与坐标轴法

    壹 ❀ 引 本题来自Leetcode74. 搜索二维矩阵,虽然难度是中等,但如果站在做出来的角度,你会发现其实并不难,题目描述如下: 编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值. ...

  9. NC14700 追债之旅

    题目链接 题目 题目描述 小明现在要追讨一笔债务,已知有n座城市,每个城市都有编号,城市与城市之间存在道路相连(每条道路都是双向的),经过任意一条道路需要支付费用.小明一开始位于编号为1的城市,欠债人 ...

  10. NC20115 [HNOI2015]菜肴制作

    题目链接 题目 题目描述 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予1到N的顺序编号,预估质量最高的菜肴编号 ...