【iOS】Tagged Pointer

Tagged Pointer

内存布局

  • 代码段:编译之后的代码
  • 数据段
    • 字符串常量:比如NSString *str = @"123"
    • 已初始化数据:已初始化的全局变量、静态变量等
    • 未初始化数据:未初始化的全局变量、静态变量等
  • 堆:通过alloc、malloc、calloc等动态分配的空间,分配的内存空间地址越来越大-
  • 栈:函数调用开销,比如局部变量。分配的内存空间地址越来越小

Tagged Pointer

  • 从64bit开始,iOS引入了Tagged Pointer技术,用于优化NSNumber、NSDate、NSString等小对象的存储
  • 在没有使用Tagged Pointer之前, NSNumber等对象需要动态分配内存、维护引用计数等,NSNumber指针存储的是堆中NSNumber对象的地址值
  • 使用Tagged Pointer之后,NSNumber指针里面存储的数据变成了:Tag + Data,也就是将数据直接存储在了指针中
  • 当指针不够存储数据时,才会使用动态分配内存的方式来存储数据
  • objc_msgSend能识别Tagged Pointer比如NSNumber的intValue方法,直接从指针提取数据,节省了以前的调用开销

在小对象的时候, 使用Tagged Pointer,NSNumber指针里面存储的数据变成了:Tag + Data,也就是将数据直接存储在了指针中,不在需要存取来获取值了。

我们分别打印abcdefghijk和abc字符串的类型。

NSString *str1 = [NSString stringWithFormat:@"abc"];

NSString *str2 = [NSString stringWithFormat:@"abcdefghijk"];

NSLog(@"\n[str1 class]=%@\n[str2 class]=%@",[str1 class],[str2 class]);

打印结果:

根据打印发现str1是NSTaggedPointerString类型,是不通过set方法找对象的。

我们也可以在源码中找到相关实现,

    1. 在NSObject.mm中查找retain方法的实现
objc 复制代码
- (id)retain {
	return ((id)self)->rootRetain();
}
    1. 点击进入rootRetain方法,我们可以在里面找到:
      if (isTaggedPointer())
      return (id)this;
      也就是说如果是TaggedPointer类型,直接返回,不需要根据指针查找。

判断是否是TaggedPointer

我们点击isTaggedPointer方法

_objc_isTaggedPointer(const void * _Nullable ptr)

{

return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;

}

  • define _OBJC_TAG_MASK 1UL
objc 复制代码
#if TARGET_OS_OSX && __x86_64__
#   define OBJC_MSB_TAGGED_POINTERS 0
#else
#   define OBJC_MSB_TAGGED_POINTERS 1
#endif


#if OBJC_MSB_TAGGED_POINTERS
#   define _OBJC_TAG_MASK (1UL<<63)
#else
#   define _OBJC_TAG_MASK 1UL
#endif

在判断是否是TaggedPointer的时候,在iOS平台和MAC平台还是不太一样的

1、iOS平台,需要把1向左移动63位,也就是最高有效位是1(第64bit)

2、在Mac平台,最低有效位是1

面试题

  1. 什么是Tagged Pointer?

    答:Tagged Pointer是一种优化技术,用于存储小对象(如NSNumber、NSDate和NSString)的值。与普通对象不同,Tagged Pointer直接将数据存储在指针本身,而不是存储在堆上的内存块。这种技术利用了64位指针的高位来存储类型信息和实际数据,从而避免了分配和释放内存的开销,提高了性能和效率。

  2. Tagged Pointer的工作原理是什么?

    答:

    Tagged Pointer的工作原理基于将指针的部分位 用作标记(tag)和数据存储。具体实现如下:

    1. 标记位(Tag Bits):在64位指针的高位部分,用若干位来存储标记信息。这些标记位用来区分不同类型的Tagged Pointer(如NSNumber、NSDate等)。
    2. 数据位(Data Bits):在剩余的位中直接存储实际数据。例如,对于NSNumber,可以直接存储整数值或浮点数值。
    3. 类型检测:在需要时,通过检测指针的高位标记,判断该指针是否是Tagged Pointer以及它的类型。
  3. 如果检测一个指针是否是Tagged Pointer?

    答:

    检测一个指针是否是Tagged Pointer,可以通过检查指针的高位标记。具体实现方式因不同版本的Objective-C运行时而异,但常见的方式是检查指针是否设置了某些特定位。例如,在64位系统上,如果指针的最高位为1,则该指针可能是Tagged Pointer。代码示例如下:

BOOL isTaggedPointer(id pointer) {

return ((uintptr_t)pointer & _OBJC_TAG_MASK) != 0;

}

其中,_OBJC_TAG_MASK是用于检测Tagged Pointer的掩码。

  1. 给出一个Tagged Pointer NSNumber的示例,并解释其内部结构

假设我们有一个Tagged Pointer类型的NSNumber对象,其内部结构可能如下:

  • 标记位:在指针的高位,用于标记该指针是Tagged Pointer以及它的类型(例如,NSNumber)。
  • 数据位:在指针的低位,存储实际的数值数据。

例如,假设一个64位指针的结构如下:

css 复制代码
[63 ... 60] [59 ... 4] [3 ... 0]
  标记位       数据位    类型标记

假设标记位为0b1110(表示NSNumber),类型标记为0b0001(表示整数类型),数据位为0b0000000000000000000000000000000000000000000000000000000000001101(表示整数13)。则这个Tagged Pointer的值表示一个NSNumber对象,其数值为13。

怎么理解这个?

这个比特位分布,和之前介绍的 isa_t 结构有些不同。这个新的比特位分布是 Objective-C 运行时系统中另一种优化技术 - "Packed Tagged Pointer"。

下面我来解释一下这个结构的每个部分:

63 ... 60\] 标记位 (4 bits): 这 4 个比特位用于标识这是一个 Packed Tagged Pointer,而不是普通的 isa 指针。 它们会被设置为一个特殊的标记值,用于在运行时快速识别这种指针。 \[59 ... 4\] 数据位 (56 bits): 这 56 个比特位用于存储对象的数值信息和类信息。 具体的编码方式取决于对象的类型。 \[3 ... 0\] 类型标记 (4 bits): 这 4 个比特位用于标识对象的具体类型,比如整数、浮点数、字符串等。 运行时系统会根据这个类型标记来解析存储在数据位中的实际值。 与之前介绍的 Tagged Pointer 相比,这种 Packed Tagged Pointer 的优势是能够存储更多的数据信息,提高了存储密度。

相关推荐
YongPagani14 小时前
Mac安装Homebrew
macos
Byron Loong15 小时前
【系统】Mac系统和Linux 指令对比
linux·macos·策略模式
软件小滔18 小时前
拖拽出来的专业感
经验分享·macos·mac·应用推荐
搜狐技术产品小编202318 小时前
精通 UITableViewDiffableDataSource——从入门到重构的现代 iOS 列表开发指南
ios·重构
coooliang19 小时前
Macos下载元神 ipa文件
macos
Benny的老巢19 小时前
【n8n工作流入门02】macOS安装n8n保姆级教程:Homebrew与npm两种方式详解
macos·npm·node.js·n8n·n8n工作流·homwbrew·n8n安装
tangweiguo0305198719 小时前
SwiftUI 状态管理完全指南:从 @State 到 @EnvironmentObject
ios
程序员agions19 小时前
Unity 游戏开发邪修秘籍:从入门到被策划追杀的艺术
unity·cocoa·lucene
望眼欲穿的程序猿20 小时前
基于Linux&MacOS 开发Ai8051U
linux·运维·macos
TESmart碲视20 小时前
M4芯片MacBook支持多显示器吗?mac如何与KVM切换器使用。
macos·计算机外设·mst·kvm切换器·双屏kvm切换器