iOS - Tagged Pointer

news/2025/1/11 13:54:41/

1. 基本结构

// Tagged Pointer 的内存布局
union TaggedPointer {uintptr_t bits;  // 完整的指针值struct {uintptr_t data     : 60;  // 数据部分uintptr_t tag      : 4;   // 类型标记};// 扩展类型struct {uintptr_t extData  : 52;  // 扩展数据uintptr_t extTag   : 8;   // 扩展标记uintptr_t isExt    : 4;   // 是否是扩展类型};
};

2. 类型判断

// 判断是否是 Tagged Pointer
static inline bool 
isTaggedPointer(const void *ptr) {return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}// 获取类型标记
static inline uintptr_t 
getTaggedPointerTag(const void *ptr) {return ((uintptr_t)ptr >> _OBJC_TAG_SLOT_SHIFT) & _OBJC_TAG_MASK;
}

3. 支持的数据类型

3.1 基本类型

// NSNumber 的 Tagged Pointer 实现
+ (NSNumber *)numberWithInt:(int)value {// 如果值在 Tagged Pointer 范围内if (value >= MIN_TAGGED_INT && value <= MAX_TAGGED_INT) {uintptr_t tagged = ((uintptr_t)value << 4) | NSNumberTag;return (__bridge id)(void *)tagged;}// 否则创建普通对象return [[NSNumber alloc] initWithInt:value];
}

3.2 字符串类型

// NSString 的 Tagged Pointer 实现
+ (NSString *)stringWithSmallString:(const char *)str {size_t length = strlen(str);if (length <= 7) {  // 可以用 Tagged Pointer 存储uintptr_t tagged = 0;for (size_t i = 0; i < length; i++) {tagged |= ((uintptr_t)str[i] << (i * 8));}tagged |= (NSStringTag << 60);  // 添加标记return (__bridge id)(void *)tagged;}return [[NSString alloc] initWithUTF8String:str];
}

4. 内存管理

4.1 引用计数

// Tagged Pointer 不需要引用计数
id objc_retain(id obj) {if (isTaggedPointer(obj)) return obj;return obj->retain();
}void objc_release(id obj) {if (isTaggedPointer(obj)) return;return obj->release();
}

4.2 内存优化

// 直接存储数据,无需额外内存分配
+ (instancetype)optimizedNumberWithInt:(int)value {if (canBeTaggedPointer(value)) {return makeTaggedPointer(value);}return [self newNumberWithInt:value];
}

5. 消息发送

id objc_msgSend_tagged(id self, SEL _cmd, ...) {// 1. 获取类型标记uintptr_t tag = getTaggedPointerTag(self);// 2. 获取对应的类Class cls = objc_getTaggedPointerClass(tag);// 3. 查找方法IMP imp = lookUpImpOrForward(cls, _cmd);// 4. 调用方法return imp(self, _cmd, ...);
}

6. 性能优化

6.1 空间优化

// 普通对象
struct NSNumber {Class isa;int value;      // 至少需要 16 字节
};// Tagged Pointer
// 直接使用指针存储值,只需要 8 字节
uintptr_t taggedNumber = (value << 4) | tag;

6.2 时间优化

// 普通对象访问
int getValue(NSNumber *num) {// 1. 解引用 isa// 2. 解引用获取值return num->_value;
}// Tagged Pointer 访问
int getTaggedValue(NSNumber *num) {// 直接从指针中提取值return (uintptr_t)num >> 4;
}

7. 限制和注意事项

7.1 大小限制

// 数据大小限制
#define TAGGED_POINTER_MASK  0xF000000000000000
#define TAGGED_POINTER_DATA  0x0FFFFFFFFFFFFFFFbool canBeTagged(size_t size) {// 60位数据位的限制return size <= (sizeof(uintptr_t) * 8 - 4);
}

7.2 类型限制

// Tagged Pointer 支持的类型定义
static Class taggedPointerClasses[] = {[OBJC_TAG_NSAtom]            = NSAtom,              // 0[OBJC_TAG_NSString]          = NSString,            // 1[OBJC_TAG_NSNumber]          = NSNumber,            // 2[OBJC_TAG_NSIndexPath]       = NSIndexPath,         // 3[OBJC_TAG_NSManagedObjectID] = NSManagedObjectID,   // 4[OBJC_TAG_NSDate]            = NSDate,               // 5[OBJC_TAG_NSDateTS]          = NSDateTS,             // 6[OBJC_TAG_NSDecimalNumber]   = NSDecimalNumber       // 7
};

8. 实际应用

8.1 字符串优化

NSString *str1 = @"abc";     // 可能使用 Tagged Pointer
NSString *str2 = @"这是一个很长的字符串";  // 普通对象

Tagged Pointer 的优势:

  1. 减少内存分配
  2. 提高访问速度
  3. 减少引用计数操作
  4. 优化内存使用

这种优化对于小对象的处理特别有效,是一个重要的性能优化手段。


http://www.ppmy.cn/news/1562244.html

相关文章

朝天椒USB服务器在银泰证券虚拟化超融合场景的应用案例

在数字化浪潮席卷金融行业的今天&#xff0c;银泰证券作为业内知名的金融机构&#xff0c;始终致力于提升业务运营效率与数据安全性。面对虚拟化超融合场景下各种认证U盾的管理挑战&#xff0c;银泰证券选择了朝天椒USB服务器作为其解决方案&#xff0c;成功实现了U盾在虚拟机中…

pytest 参数介绍

命令行参数描述常见使用案例-v / --verbose显示每个测试用例的详细信息&#xff0c;包括测试名称和状态pytest -v-s / --captureno禁用输出捕获&#xff0c;允许 print() 输出显示pytest -s-q / --quiet安静模式&#xff0c;减少输出&#xff0c;仅显示每个测试的通过/失败结果…

电脑硬盘系统迁移及问题处理

一、系统迁移准备 1、确认你的电脑主板是否支持安装两块硬盘,如电脑主板有多个M2硬盘接口,我们将新硬盘安装到主板上,原来的老硬盘安装在第二个接口上,主板只有一个M2接口的话可以使用移动硬盘盒。 2、新硬盘安装好后,我们进入原来的系统,在 此电脑–右键–管理–磁盘管…

3.python基础语法-上

文章目录 1.常量和表达式2.变量和类型2.1.变量的语法2.1.1定义变量2.2.2使用变量 2.2变量类型2.2.1整数2.2.2浮点数(小数)2.2.3字符串2.2.4布尔2.2.5其他 2.3为什么要有这么多类型?2.4动态类型特性 3.注释3.1注释是什么3.2注释的语法3.2.1注释行3.2.2文档字符串 3.3注释的规范…

Python基于YOLOv8和OpenCV实现车道线和车辆检测

使用YOLOv8&#xff08;You Only Look Once&#xff09;和OpenCV实现车道线和车辆检测&#xff0c;目标是创建一个可以检测道路上的车道并识别车辆的系统&#xff0c;并估计它们与摄像头的距离。该项目结合了计算机视觉技术和深度学习物体检测。 1、系统主要功能 车道检测&am…

ASP.NET Core 实现微服务 -- Polly 服务降级熔断

在我们实施微服务之后&#xff0c;服务间的调用变的异常频繁。多个服务之间可能是互相依赖的关系。某个服务出现故障或者是服务间的网络出现故障都会造成服务调用的失败&#xff0c;进而影响到某个业务服务处理失败。某一个服务调用失败轻则造成当前相关业务无法处理&#xff1…

从configure.ac到构建环境:解析Mellanox OFED内核模块构建脚本

在软件开发过程中,特别是在处理复杂的内核模块如Mellanox OFED(OpenFabrics Enterprise Distribution)时,构建一个可移植且高效的构建系统至关重要。Autoconf和Automake等工具在此过程中扮演着核心角色。本文将深入解析一个用于准备Mellanox OFED内核模块构建环境的Autocon…

4 $ 符号

引用变量 普通变量&#xff1a;使用 $ 符号引用变量的值。name"John" echo "Hello, $name" # 输出: Hello, John特殊参数 $#&#xff1a;传递给脚本的参数个数。 echo "Number of arguments: $#"$0&#xff1a;脚本的名称。 echo "Script …