iOS - Tagged Pointer

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.rhkb.cn/news/502951.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产编辑器EverEdit - 两种删除空白行的方法

1 使用技巧&#xff1a;删除空白行 1.1 应用场景 用户在编辑文档时&#xff0c;可能会遇到很多空白行需要删除的情况&#xff0c;比如从网页上拷贝文字&#xff0c;可能就会存在大量的空白行要删除。 1.2 使用方法 1.2.1 方法1&#xff1a; 使用编辑主菜单 选择主菜单编辑 …

李宏毅机器学习笔记-Transformer

目录 1. Seq2seq 2. encoder Transformer 中的 Block 结构 3. Decoder 4.Encoder和Decoder间的信息传递 5.Training 6.Tips 1. Seq2seq Transformer 是一个seq2seq的model。Seq2seq指的是input是一个序列&#xff0c;输出也是一个序列&#xff0c;输出的长度是由机器自己…

GitLab集成Runner详细版--及注意事项汇总【最佳实践】

一、背景 看到网上很多用户提出的runner问题其实实际都不是问题&#xff0c;不过是因为对runner的一些细节不清楚导致了误解。本文不系统性的介绍GitLab-Runner&#xff0c;因为这类文章写得好的特别多&#xff0c;本文只汇总一些常几的问题/注意事项。旨在让新手少弯路。 二、…

指针 const 的组合

1、首先来了解一下常量 const int num 5&#xff1b; 那么num的值是5&#xff0c; num的值不可修改 2、来了解一下指针 int value 5; int* p &value; 我喜欢吧指针和类型放一起&#xff0c;来强调p是一个指针类型&#xff0c; 而赋值的时候就得赋值一个int类型的地址…

《C++11》各种初始化方式的详细列举与对比

在 C 中&#xff0c;初始化对象的方式多种多样。随着 C 标准的演进&#xff0c;特别是 C11 的引入&#xff0c;初始化方式得到了显著的扩展和改进。本文将详细列举 C 中的各种初始化方式&#xff0c;并对它们进行对比&#xff0c;帮助开发者更好地理解和应用这些特性。 1. C98…

前端小案例——520表白信封

前言&#xff1a;我们在学习完了HTML和CSS之后&#xff0c;就会想着使用这两个东西去做一些小案例&#xff0c;不过又没有什么好的案例让我们去练手&#xff0c;本篇文章就提供里一个案例——520表白信封 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主…

【Vim Masterclass 笔记05】第 4 章:Vim 的帮助系统与同步练习(L14+L15+L16)

文章目录 Section 4&#xff1a;The Vim Help System&#xff08;Vim 帮助系统&#xff09;S04L14 Getting Help1 打开帮助系统2 退出帮助系统3 查看具体命令的帮助文档4 查看帮助文档中的主题5 帮助文档间的上翻、下翻6 关于 linewise7 查看光标所在术语名词的帮助文档8 关于退…

10-C语言项目池

C语言项目池 《个人通讯录》 《火车订票系统》 管理员用户1录入火车票信息区间查询/购票2显示火车票信息打印购票信息3查询火车票信息退票4修改火车票信息5添加火车票信息 《学生学籍管理系统》 1录入学生信息2添加学生信息3显示学生信息4查找学生信息5删除学生信息6修改学…

Android 绘制学习总结

1、刷新率介绍 我们先来理一下基本的概念&#xff1a; 1、60 fps 的意思是说&#xff0c;画面每秒更新 60 次 2、这 60 次更新&#xff0c;是要均匀更新的&#xff0c;不是说一会快&#xff0c;一会慢&#xff0c;那样视觉上也会觉得不流畅 3、每秒 60 次&#xff0c;也就是 1…

每日一题:BM1 反转链表

文章目录 [toc]问题描述数据范围示例 C代码实现使用栈实现&#xff08;不符合要求&#xff0c;仅作为思路&#xff09; 解题思路 - 原地反转链表步骤 C语言代码实现 以前只用过C刷过代码题目&#xff0c;现在试着用C语言刷下 问题描述 给定一个单链表的头结点 pHead&#xff…

78、使用爱芯派2_AX630C开发板 3.2T高有效算力 低功耗 支持AI-ISP真黑光实验

基本思想:使用爱心元智最新的版本开发板进行实验 AX630C、AX620Q 都是 620E 这一代 一、参考这个官方教程,先把代码在本地交叉编译完成 https://github.com/AXERA-TECH/ax620e_bsp_sdk 然后在拷贝到620c设备上 root@ax630c:~/ax620e_bsp_sdk/msp/out/arm64_glibc/bin# ./…

【Redis经典面试题七】Redis的事务机制是怎样的?

目录 一、Redis的事务机制 二、什么是Redis的Pipeline&#xff1f;和事务有什么区别&#xff1f; 三、Redis的事务和Lua之间有哪些区别&#xff1f; 3.1 原子性保证 3.2 交互次数 3.3 前后依赖 3.4 流程编排 四、为什么Lua脚本可以保证原子性&#xff1f; 五、为什么R…

企业网络性能监控

什么是网络性能监控 网络性能监控&#xff08;NPM&#xff09;是指对计算机网络的性能进行持续测量、分析和管理的过程&#xff0c;通过监控流量、延迟、数据包丢失、带宽利用率和正常运行时间等关键指标&#xff0c;确保网络高效、安全地运行&#xff0c;并将停机时间降至最低…

【开源】创建自动签到系统—QD框架

1. 介绍 QD是一个 基于 HAR 编辑器和 Tornado 服务端的 HTTP 定时任务自动执行 Web 框架。 主要通过抓包获取到HAR来制作任务模板&#xff0c;从而实现异步响应和发起HTTP请求 2. 需要环境 2.1 硬件需求 CPU&#xff1a;至少1核 内存&#xff1a;推荐 ≥ 1G 硬盘&#xff1a;推…

SUB输入5V升压充电16.8V芯片HU5912

HU5912芯片&#xff0c;作为航誉微电子有限公司推出的一款高性能升压充电管理IC&#xff0c;自其面世以来&#xff0c;便以其出色的性能和广泛的应用领域&#xff0c;受到了业界的高度关注和赞誉。本文将详细介绍HU5912芯片的技术特点、应用优势、市场定位以及其在各类电子设备…

练习(继承)

大家好&#xff0c;今天我们写几道题来巩固一下我们所学的知识&#xff0c;以便我们更好的学习新内容。 方法重写&#xff1a; 继承&#xff1a; 注&#xff1a;java中只能继承一个类 那么今天分享就到这里&#xff0c;谢谢大家&#xff01;&#xff01;&#xff01;

计算机网络 (28)虚拟专用网VPN

前言 虚拟专用网络&#xff08;VPN&#xff09;是一种在公共网络上建立私有网络连接的技术&#xff0c;它允许远程用户通过加密通道访问内部网络资源&#xff0c;实现远程办公和安全通信。 一、基本概念 定义&#xff1a;VPN是一种通过公共网络&#xff08;如互联网&#xff09…

04-spring-理-ApplicationContext的实现

实现1&#xff1a;ClassPathXmlApplicationContext 1、内部维护了 DefaultListableBeanFactory 2、通过XmlBeanDefinitionReader 读取配置文件将结果加入到 DefaultListableBeanFactory 3、没有维护 bean后置处理器 &#xff0c;可以通过在xml配置 <context:annotation-c…

STM32的LED点亮教程:使用HAL库与Proteus仿真

学习目标&#xff1a;掌握使用STM32 HAL库点亮LED灯&#xff0c;并通过Proteus进行仿真验证&#xff01; 建立HAL库标准工程 1.新建工程文件夹 新建工程文件夹建议路径尽量为中文。建立文件夹的目的为了更好分类去管理项目工程中需要的各类工程文件。 首先需要在某个位置建立工…

回归预测 | MATLAB实ELM-Adaboost多输入单输出回归预测

回归预测 | MATLAB实ELM-Adaboost多输入单输出回归预测 目录 回归预测 | MATLAB实ELM-Adaboost多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 一、极限学习机&#xff08;ELM&#xff09; 极限学习机是一种单层前馈神经网络&#xff0c;具有训练速…