YYKit @autoreleasepool 使用,优化内存
写在前面
最近再看YY大神的YYKit工具,发现在代码中经常使用@autoreleasepool,特别是在与for循环搭配使用的时候。刚开始很不能理解。
先有个概念:
自己创建的对象:使用 alloc new copy mutablecopy 以及他们的驼峰变形 allocObject newObject copyObject mutablecopyObject。这八种创建的才是自己创建的对象。
不是自己创建的:除去以上八中都不是自己创建的。
autoreleasepool:只有非自己创建的对象才会注册到离该对象最近的autoreleasepool中去。
之前对iOS的ARC的理解就是自己创建的对象,会在该对象所在是代码快(当前作用域)结束时候自动释放。无需程序员自己管理。但是如果仔细研究YYKit的代码的话,发现如果注释掉@autoreleasepool,程序一样可以正常运行,但是观察当前内存,会比在加上该句代码时候占用比更大的空间。所以自己百度了一下,这里是sunny(百度一90后iOS程序员)大神写的关于@autoreleasepool的理解,主要内容其实可以概括为 一句话"Autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop",具体我就不抄了,但是有些东西不适合初学者,我自己总结了一些,比较容易理解一点。具体看代码。
@interface ViewController ()
@property(strong, nonatomic) NSMutableArray *memoryUsageList;
@end @implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad]; //Init
_memoryUsageList1 = [NSMutableArray new]; //创建一个串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("test.autoreleasepool", DISPATCH_QUEUE_SERIAL); __block NSString *strTest;
dispatch_sync(serialQueue, ^{
for (int i = ; i < kIterationCount; i++) {
@autoreleasepool {
NSNumber *num = [NSNumber numberWithInt:i]; // 1
NSString *str = [NSString stringWithFormat:@"%d ", i]; // 2
//Use num and str...whatever...
strTest = [NSString stringWithFormat:@"%@%@", num, str]; // 3
if (i % kStep == ) {
[_memoryUsageList1 addObject:@(getMemoryUsage())]; // getM方法是获取内存的函数
NSLog(@"000----%f", getMemoryUsage());
}
}
}
});
} // 4
double getMemoryUsage(void) {
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size); double memoryUsageInMB = kerr == KERN_SUCCESS ? (info.resident_size / 1024.0 / 1024.0) : 0.0; return memoryUsageInMB;
}
让我们来分析一下当有@autoreleasepool存在的时候,代码中的1、2、3行中的内存分别是在什么时候释放。此分析建立在已经有iOS引用计数器概念的基础上。ARC其实就是编译器自动帮我们加上了retain,release等,本质还是引用计数器。
1、
1和2是相同的,在堆区分别存在NSNumber的对象和NSString的对象,栈区有对应的指针,num、str指向两个对象。当一次for循环结束的时候,栈区的两个指针由系统释放,此时堆区中的两个对象的引用计数器为0,所以一次for循环结束的时候,两个对象释放。
2、
关键是3行,首先分析strTest,每次for循环都会重新覆盖strTest之前的值,由于strTest是在viewDidLoad函数中,所以当函数结束,也就是如代码中,4行时候strTest释放,同时strTest指向的堆中的内存空间也释放。也就是for循环最后一次的"[NSString stringWithFormat:@"%@%@", num, str]"的值会释放。
这么看来好像所有的内存都已经释放了,那么@auto究竟做了什么呢?
重点:注意观察for循环,每一次for循环,在堆区都会生成一份"[NSString stringWithFormat:@"%@%@", num, str]"的内存,然后最新生成的一份内存会由strTest重新指一次,那么之前那些内存去哪了?我刚开始以为每一次for循环结束时候,之前生成的便会自动释放。该内存不是通过系统自动创建的,也就是说不是通过 alloc /new/copy/mutablecopy 创建的,所以会注册到autoreleasepool中 ,作用域无效,系统是无法自动释放的。这时候是@auto的关键了。@autoreleasepool相当于给堆中的内存添加了一个作用域,超过这个作用域堆中的内存就自动释放。所以每次遍历完,一份新生成的"[NSString stringWithFormat:@"%@%@", num, str]"作用域结束,自动释放。
那么,问题又来了。我不加@autoreleasepool,程序一样运行的很好,没出现问题。那是因为,系统在每一次的runloop中自动给我们加上了@autoreleasepool,一次runloop结束,系统就会把该循环中的所有需要release的对象清除。之所以在代码中手动添加一次,是为了防止在某一操作的时候,该操作瞬时占用的内存过大(比如for循环),导致程序瞬时的闪退。
总结:多看大神代码,那写你认为很无聊的写法,可能里面包含这对整个系统更深层次的理解。
但是发现有一些有趣的现象,例如如下的代码
for (int i = ; i < 100000; i++) {
NSNumber *num = [NSNumber numberWithInt:i]; //
NSString *str = [NSString stringWithFormat:@"%d ", i]; //
NSString *str1 = [NSString stringWithFormat:@"%@", num]; //
NSString *str2 = [NSString stringWithFormat:@"%@%@", num, str]; //4
// NSString *str3 = [[NSString alloc] initWithFormat:@"%@%@", num, str]; // ****test****
[NSArray arrayWithObject:@""]; // 5
// if (i % 10000 == 0) {
// NSLog(@"000----%f", getMemoryUsage());
// }
}
自己个人猜测:
单独执行代码1、2,打印的内存不会上升。
执行代码1和3,内存不会上升
执行代码 1+2+4 内存飙升。猜测,不同类型合并成string内存管理不一样。
单独执行5,内存飙升。
个人理解:[NSNumber numberWithInt:i]和[NSString stringWithFormat:@"%@", num]等,并没有发送autorelease消息,也就是没将他们放到autoreleasepool中。所以在代码快结束的时候他们就已经销毁了,但是某些特殊的,如[NSArray arrayWithObject:@"1234"]; 会添加到pool中,由于处于autoreleasepool中的对象延迟执行(所在runloop完毕),所以代码块结束时候,runloop并未结束,导致无法释放。
总结:当遇到大量的for循环时候,尽量使用@autoreleasepool来避免内存的延迟释放导致瞬时内存飙升。苹果推荐以下三中情况使用@autoreleasepool代码快
如果你编写的程序不是基于 UI 框架的,比如说命令行工具;
如果你编写的循环中创建了大量的临时对象;(常用)
如果你创建了一个辅助线程。
YYKit @autoreleasepool 使用,优化内存的更多相关文章
- Android性能优化之巧用软引用与弱引用优化内存使用
前言: 从事Android开发的同学都知道移动设备的内存使用是非常敏感的话题,今天我们来看下如何使用软引用与弱引用来优化内存使用.下面来理解几个概念. 1.StrongReference(强引用) 强 ...
- cocos2d 如何优化内存使用
如何优化内存使用 内存优化原理 为优化应用内存使用,开发人员首先应该知道什么最耗应用内存,答案就是纹理! 纹理几乎会占据90%应用内存.所以尽量最小化应用的纹理内存使用,否则应用很有可能会因为低内存而 ...
- cocos2d-x如何优化内存的应用
自身以前也写过cocos2d-x如何优化内存的应用,以及内存不够的情况下怎么样处置惩罚游戏.今天在微博中看到有友好简介了下内存,挺详细的.不晓得是谁写的,我纪录下. 一,IOS与图片内存 在IOS上, ...
- C++ Primer 学习笔记_98_特殊的工具和技术 --优化内存分配
特殊的工具和技术 --优化内存分配 引言: C++的内存分配是一种类型化操作:new为特定类型分配内存,并在新分配的内存中构造该类型的一个对象.new表达式自己主动执行合适的构造函数来初始化每一个动态 ...
- Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间
Redis 小白指南(三)- 事务.过期.消息通知.管道和优化内存空间 简介 <Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍> 讲的是 Redis 的介绍,以及如何 ...
- R︱foreach+doParallel并行+联用迭代器优化内存+并行机器学习算法
要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 接着之前写的并行算法paralle ...
- Android性能优化-内存优化
原文链接 Manage Your App’s Memory 前言 在任何软件开发环境中,RAM都是比较珍贵的资源.在移动操作系统上更是这样,因为它们的物理内存通常受限.尽管在ART和Dalvik虚拟机 ...
- 谷歌发布 Android 8.1 首个开发者预览版,优化内存效率
今晨,谷歌推出了 Android 8.1 首个开发者预览版,此次升级涵盖了针对多个功能的提升优化,其中包含对 Android Go (设备运行内存小于等于 1 GB)和加速设备上对机器学习的全新神经网 ...
- 【转】cocos2d-x如何优化内存的应用
原地址:http://cblog.chinadaily.com.cn/blog-942327-4327173.html 注:自身以前也写过cocos2d-x如何优化内存的应用,以及内存不够的情况下怎么 ...
随机推荐
- 深度学习原理与框架-Tensorflow基本操作-mnist数据集的逻辑回归 1.tf.matmul(点乘操作) 2.tf.equal(对应位置是否相等) 3.tf.cast(将布尔类型转换为数值类型) 4.tf.argmax(返回最大值的索引) 5.tf.nn.softmax(计算softmax概率值) 6.tf.train.GradientDescentOptimizer(损失值梯度下降器)
1. tf.matmul(X, w) # 进行点乘操作 参数说明:X,w都表示输入的数据, 2.tf.equal(x, y) # 比较两个数据对应位置的数是否相等,返回值为True,或者False 参 ...
- vue-x action 的相互调用
实现方式:分发 Action Action 通过 store.dispatch 方法触发: store.dispatch('increment')
- Erlang 笔记
集成开发环境:IntelliJ IDEA的Erlang插件 教程:www.erlang-cn.com/462.html,寻找erlang程序设计第2版pdf f():释放之前绑定过的所有变量. -ex ...
- avalon2学习教程06样式操作
avalon2的ms-css的变革思路与ms-attr一样,将多个操作合并成到一个对象里面处理,因此没有ms-css-name="value",只有ms-css="Obj ...
- avalon2学习教程 03数据填充
数据填充是一个模版最基础的功能,直接从JSON(vm)取出数据,放到适当的位置上.在静态模板中,不区分文本与HTML,只看你的字符串是否有< >来决定生成文本节点与元素节点.但MVVM中, ...
- vue项目bug-Couldn’t find preset "es2015"
在使用vue项目的时候安装了其他的插件,发现会报错 Couldn’t find preset "es2015".是因引用的插件使用了es标准,解决办法如下 npm install ...
- 关于malloc(0)的返回值问题--这两天的总结与实践篇
就像我在http://www.cnblogs.com/wuyuegb2312/p/3219659.html 文章中评论的那样,我也碰到了被提问这个malloc(0)的返回值问题,虽然感觉这样做在实际中 ...
- ArcGIS 10安装及破解
1.下载 ArcGIS 10 安装程序及破解文件后面提供电驴的下载地址(可以使用迅雷.QQ旋风等下载工具下载),下载文件是一个光盘镜像文件:? ArcGIS_Desktop10_122519.iso. ...
- AnimCheckBox按钮点击动画效果《IT蓝豹》
AnimCheckBox按钮点击动画效果 AnimCheckBox按钮点击动画效果,点击选中后勾选框选择效果,很不错的动画功能.项目来源:https://github.com/lguipeng/Ani ...
- stringBuffer和stringBulider的区别
今天去面试了,问了最基础的stringBuffer和stringBulider的区别,我没有回答出来.之前就知道自己的基础很差,没想到这么差. 网上看了一下资料,stringBuffer和string ...