iOS - AutoreleasePool
1. 基本数据结构
// AutoreleasePool 的基本结构
struct AutoreleasePoolPage {static pthread_key_t const key = AUTORELEASE_POOL_KEY;magic_t const magic;id *next; // 指向下一个可存放对象的地址pthread_t const thread; // 所属线程AutoreleasePoolPage * const parent; // 双向链表结构AutoreleasePoolPage *child;uint32_t const depth;uint32_t hiwat;// 大小固定为 4096 字节(一个虚拟内存页的大小)static size_t const SIZE = PAGE_MAX_SIZE;
}
2. 存储结构
class AutoreleasePoolPage {AutoreleasePoolPage * const parent;AutoreleasePoolPage *child;// 存储空间id *begin() { return (id *) ((uint8_t *)this+sizeof(*this)); }id *end() { return (id *) ((uint8_t *)this+SIZE); }
}
2.2 哨兵对象
#define POOL_BOUNDARY nil // 池边界标记
static inline void *push() {id *dest = autoreleaseFast(POOL_BOUNDARY);return dest;
}
3. 线程关系
3.1 TLS存储
// 每个线程都有自己的 AutoreleasePool 栈
static pthread_key_t key;
static void tls_dealloc(void *p) {if (p == (void*)EMPTY_POOL_PLACEHOLDER) return;AutoreleasePoolPage *page = (AutoreleasePoolPage*)p;page->kill(); // 清理操作
}
3.2 线程本地存储初始化
void tls_init() {_objc_pthread_key = pthread_key_create(&_objc_pthread_destroyspecific);AutoreleasePoolPage::key = tls_create(&_objc_autoreleasepool_deallocate);
}
4. 对象管理
4.1 添加对象
static inline id *autoreleaseFast(id obj) {AutoreleasePoolPage *page = hotPage();if (page && !page->full()) {return page->add(obj);} else if (page) {return autoreleaseFullPage(obj, page);} else {return autoreleaseNoPage(obj);}
}
4.2 清理对象
void releaseAll() {// 释放所有autorelease对象AutoreleasePoolPage *page = this;while (page->child) page = page->child;do {page->releaseUntil(page->begin());} while ((page = page->parent));
}
5. 生命周期管理
5.1 创建时机
// 1. 显式创建
@autoreleasepool {// 代码块
}// 2. RunLoop 相关
void _wrapRunLoopWithAutoreleasePool(void) {@autoreleasepool {// RunLoop 逻辑}
}
5.2 释放时机
// 1. @autoreleasepool 块结束
{void *token = objc_autoreleasePoolPush();// ... objc_autoreleasePoolPop(token);
}// 2. RunLoop 迭代结束
void _runLoopIterationDidEnd() {objc_autoreleasePoolPop(currentPool);
}
6. 内存管理
6.1 页面管理
void *push() {id *dest;if (DebugPoolAllocation) {// ...debug code...}dest = autoreleaseFast(POOL_BOUNDARY);return dest;
}static inline void pop(void *token) {AutoreleasePoolPage *page;id *stop;page = pageForPointer(token);stop = (id *)token;page->releaseUntil(stop);
}
6.2 溢出处理
static id *autoreleaseFullPage(id obj, AutoreleasePoolPage *page) {// 当前页满了,创建新页AutoreleasePoolPage *next = new AutoreleasePoolPage(page);page->child = next;return next->add(obj);
}
7. 特殊情况处理
7.1 嵌套池
@autoreleasepool { // 外层池NSString *str1 = @"1";@autoreleasepool { // 内层池NSString *str2 = @"2";} // str2 被释放
} // str1 被释放
7.2 异常处理
void unwinding_cleanup() {// 异常展开时确保 AutoreleasePool 正确清理AutoreleasePoolPage *page = hotPage();if (page) {pop(page->begin());}
}
8. 性能优化
8.1 快速路径
static inline id autorelease(id obj) {ASSERT(obj);id *dest __unused = autoreleaseFast(obj);return obj;
}
8.2 空间优化
// 使用一页虚拟内存(4KB)作为存储单元
#define PAGE_MAX_SIZE 4096
9. 最佳实践
9.1 手动管理
// 处理大量临时对象
for (int i = 0; i < largeNumber; i++) {@autoreleasepool {// 创建临时对象的代码}
}
9.2 子线程处理
dispatch_async(dispatch_get_global_queue(0, 0), ^{@autoreleasepool {// 子线程代码}
});
10. 注意事项
1. 内存峰值:
// 不好的做法
for (int i = 0; i < largeNumber; i++) {// 创建autorelease对象
} // 在循环结束才释放// 好的做法
for (int i = 0; i < largeNumber; i++) {@autoreleasepool {// 创建autorelease对象} // 每次迭代都释放
}
2. 线程安全:
// 每个线程维护自己的autoreleasepool栈
+ (void)threadEntryPoint {@autoreleasepool {// 线程代码}
}
3. RunLoop关系:
// RunLoop每次迭代都会创建和释放autoreleasepool
void runLoopMain() {while (running) {@autoreleasepool {// 一次RunLoop迭代runLoopIteration();}}
}
这里涵盖了AutoreleasePool 的主要实现细节和使用注意事项。理解这些内容对于正确使用AutoreleasePool和优化内存管理非常重要。
总结说明:
1. 每个AutoreleasePoolPage 存储了一个静态变量key和成员变量thread
2. 多线程共用一个 key 用于从 TLS 中获取当前线程的的 page 实例对象
3. 在 TLS 内部获取当前的线程,使用 key 从当前线程的一个哈希表中取出对应的 page
4. 一个线程可能有多个 page,TLS 存储双向链表中当前线程对应的最后一个page和key之间的映射
5. 成员变量 thread 用于判断遍历过程中的 page节点是否是当前线程的page,如果不是则跳过,向前跳一个节点(page)
相关文章:
iOS - AutoreleasePool
1. 基本数据结构 // AutoreleasePool 的基本结构 struct AutoreleasePoolPage {static pthread_key_t const key AUTORELEASE_POOL_KEY;magic_t const magic;id *next; // 指向下一个可存放对象的地址pthread_t const thread; // 所属线程AutoreleasePoolPage …...
1.CSS的复合选择器
1.1 什么是复合选择器 在CSS中,可以根据选择器的类型把选择器分为基础选择器和复合选择器,复合选择器是建立在基础选择器之上,对基础选择器进行组合形成的。 复合选择器可以更精准、更高效的选择目标元素(标签) 复…...
优质内容在个人IP运营中的重要性:以开源AI智能名片商城小程序为应用实例的深度探讨
摘要:在数字化时代,个人品牌(IP)的塑造与传播已成为各行各业提升影响力、吸引用户关注、促进商业转化的关键策略。优质内容作为连接个人IP与目标受众的桥梁,其在个人IP运营中的重要性不言而喻。本文旨在深入探讨优质内…...
Kafka性能测试
kafka是一个大数据消息队列(可以看做为缓存软件) 功能测试:能够读写数据 性能测试:1、测试生产者每秒往kafka写入的最大吞吐量 2、测试消费者每秒从kafka里获取消息最大吞吐量 硬件 3台物理机组成的kafka集群。 内存121G、24…...
解决Docker冲突问题
错误:docker-ce-cli conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 错误:docker-ce conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 您可以尝试添加 --skip-broken 选项来解决该问题 您可以尝试执行:…...
新手入门 React .tsx 项目:从零到实战
🚀 新手入门 React .tsx 项目:从零到实战 💻✨ 如果你是 React 新手,刚接触 .tsx 文件,不要担心!跟着这份指南,一步一步来,你很快就能上手了!👇 Ὅ…...
基于可信数据空间的企业数据要素与流通体系建设(附ppt 下载)
近期,可信数据空间会议召开。大数据系统软件国家工程研究中心总工程师王晨发表了题为《基于可信数据空间的企业数据要素与流通体系建设》主旨演讲。 篇幅限制,部分内容如下:...
二维数组:求最大元素及其所在的行坐标及列坐标(PTA)C语言
求出NM整型数组的最大元素及其所在的行坐标及列坐标(如果最大元素不唯一,选择位置在最前面的一个)。 函数接口定义: int fun(int array[N][M]) ; 注意:函数只需靠return返回最大元素的值, 行、列坐标通过…...
WebRtc01: 课程导学、框架介绍
应用 难点 课程大纲 学习收获 涉及内容 概述 用途 学习收获...
HQChart使用教程30-K线图如何对接第3方数据44-DRAWPIE数据结构
HQChart使用教程30-K线图如何对接第3方数据44-DRAWPIE数据结构 效果图DRAWPIEHQChart代码地址后台数据对接说明示例数据数据结构说明效果图 DRAWPIE DRAWPIE是hqchart插件独有的绘制饼图函数,可以通过麦语法脚本来绘制一个简单的饼图数据。 饼图显示的位置固定在右上角。 下…...
【cuda学习日记】2.2 使用2维网络(grid)和2维块(block)对矩阵进行求和
在2.0中进行了用一维网格和块对一维向量进行了求和。 在2.1中例化了二维的网格和块。 接下来进行2维网络(grid)和2维块(block)对矩阵进行求和。 #include <stdio.h> #include <stdlib.h> #include <time.h> #i…...
深度学习中CUDA环境安装教程
首先说明,本人是小白,一次安装,可能有不对的地方,望包含。 安装CUDA 因为我们是深度学习,很多时候要用到gpu进行训练,所以我们需要一种方式加快训练速度。 通俗地说,CUDA是一种协助“CPU任务分…...
IDEA的常用设置
目录 一、显示顶部工具栏 二、设置编辑区字体按住鼠标滚轮变大变小(看需要设置) 三、设置自动导包和优化导入的包(有的时候还是需要手动导包) 四、设置导入同一个包下的类,超过指定个数的时候,合并为*&a…...
【VUE+ElementUI】通过接口下载blob流文件设置全局Loading加载进度
下载Blob流文件,并以服务形式显示文件下载进度 1、下载接口 增加 config参数,并用...config将该属性加入到请求中; xxapi.js文件中设置downloadFile下载接口 // 下载文件 export function downloadFile(data, config) {return request({ur…...
算法的五个重要特性和4个基本标准
五个特性: 1、有穷性:一个算法必须执行有穷步后结束、 2、确定性:对于每种情况下所应执行的操作,在算法中都应该有确切的规定,不会产生二义性, 使得算法的执行者和阅读者都能明确其含义以及如何执行。 3、…...
svelte5中使用react组件
在svelet5中导入并使用react组件库 svelte5中使用react组件 svelte5中使用react组件 在svelet5中导入并使用react组件库, 示例项目地址:https://github.com/shenshouer/my-svelte-react 在svelte5中当前还有问题,无法将children传递到react中渲染 使用…...
iOS - 自定义引用计数(MRC)
自定义引用计数(Custom Reference Counting)是指类可以通过重写 retain/release 等方法来实现自己的引用计数管理机制。这通常用于特殊场景下的内存管理优化。 1. 判断是否使用自定义引用计数 inline bool objc_object::hasCustomRR() {// 检查类是否…...
北航现实场景无人机VLN新基准! OpenUAV:面向真实环境的无人机视觉语言导航,平台、基准与方法
作者:Xiangyu Wang, Donglin Yang, Ziqin Wang, Hohin Kwan, Jinyu Chen, Wenjun Wu1, Hongsheng Li, Yue Liao, Si Liu 单位:北京航空航天大学人工智能学院,香港中文大学多媒体实验室,感知与交互智能中心 原文链接:…...
OpenCV计算机视觉 08 图像的旋转
图像的旋转 下面是一张小猪佩奇的照片,请进行顺时针90度,逆时针90度,180度旋转 方法一:使用了 NumPy 库的 np.rot90() 函数来实现图像的旋转 np.rot90(img, k-1) 表示将输入的图像 img 顺时针旋转 90 度, np.rot90(…...
C++感受15-Hello STL 泛型启蒙
生鱼片和STL的关系,你听过吗?泛型编程和面向对象编程,它们打架吗?行为泛型和数据泛型,各自的目的是? 0 楔 俄罗斯生鱼片,号称俄罗斯版的中国烤鸭,闻名于世。其鱼肉,源于…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
