iOS ARC + AutoReleasePool 实现机制

自动引用计数ARC(Automatic Reference Count)

  • 什么是引用计数?

一个简单而有效的管理对象生命周期的方式。当我们创建一个新对象的时候,它的引用计数为 1,当有一个新的指针指向这个对象时,我们将其引用计数加 1,当某个指针不再指向这个对象是,我们将其引用计数减 1,当对象的引用计数变为 0 时,说明这个对象不再被任何指针指向了,这个时候我们就可以将对象销毁,回收内存

  • ARC自动对象内存管理
  1. 编译器综合保留/释放调用
  2. 编译器遵守并强制执行库约定
  3. 与retain/release代码完全互操作
  • ARC新的运行时特性:
  1. 销毁弱指针
  2. 高效的性能优化
  3. 没有新的运行时内存模型
  4. 没有自动化的malloc/free, CF等。
  5. 没有垃圾收集器(无堆扫描,整个应用程序没有暂停,无不确定性释放)
  • ARC是如何工作的?
编译器为您插入retain/release/autorelease
- (NSString*) fullName {
 return [[NSString alloc] initWithFormat: @"%@ %@",
 self.firstName, self.lastName];
}
  • 指针使对象保持活动状态 (当没有更多的引用存在时,对象死亡)

  • 指针意味着“所有权” (想想你的对象)

  • 停止考虑保留/释放/自动释放调

  • 这对代码有什么影响?

  1. 没有GC开销:(没有延迟的销毁地址,没有应用程序暂停,没有非决定论)
  2. Objective-C性能改进(比NSObject retain/release,@autoreleasepool,objc_msgSend 更快)
  3. 从自动释放池回收(较低的存储压力,20倍更快的保留/自动释放回报)
  • ARC总结:
  1. 编译器合成保留/释放,释放弱指针,新的语言规则,一个更简单的实现方式
  2. 编写代码自然,在必要时中断周期,不要担心“保留”,编写优秀的应用程序
  3. Objective-C,块指针,局部变量、全局变量、参数、实例变量……,四种不同的所有权

自动释放池AutoReleasePool

Autorelease Pool是一个可以放置多个对象指针的对象池,当Autorelease Pool被销毁时,转化所有Autorelease Pool中的对象执行引用计数-1操作,这时候才会回收对象。相当于加入Autorelease Pool的对象被延迟释放了。

作用域结束就会被回收,那么如何保证拿到返回的值,
这个时候aotoreleasepool就会延时释放,
确保用户能正常拿到值后被销毁
- (NSString*) fullName {
 return [[NSString alloc] initWithFormat: @"%@ %@",
 self.firstName, self.lastName];
}
  • 自动释放池在ARC情况下如何使用?
在Runloop一个循环结束前,就会出现很多临时变量str不用了,但是占用内存的情况。
所以这里手动加上@autoreleasepool {}代码块,每次循环都创建一个新的AutoRelease Pool,str会被加入到这个新的AutoRelease Pool中,
在每次进行循环结束时,AutoRelease Pool被释放,从而str也被及时释放,内存能够得到及时的清理

for (int i = 0; i < 1000000; i++) {
    @autoreleasepool {
        NSString *str = [NSString stringWithFormat:@"Hello + %d", i];
    }
}
  • 自动释放池的实现原理
struct __AtAutoreleasePool {
  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
  void * atautoreleasepoolobj;
};

__AtAutoreleasePool是一个结构体,在构造函数和析构函数里,
分别调用了objc_autoreleasePoolPush()和objc_autoreleasePoolPop(atautoreleasepoolobj)方法。
objc_autoreleasePoolPush是在创建自动发布池,
objc_autoreleasePoolPop是在销毁Autorelease Pool
  • AutoreleasePoolPage
autorelease方法会把对象存储到AutoreleasePoolPage的链表里
等到auto release pool被释放的时候,把链表内存储的对象删除
所以,AutoreleasePoolPage就是自动释放池的内部实现

void *
objc_autoreleasePoolPush(void)
{
    return AutoreleasePoolPage::push();
}

class AutoreleasePoolPage
{
    magic_t const magic;
    id *next;
    pthread_t const thread;
    AutoreleasePoolPage * const parent;
    AutoreleasePoolPage *child;
    uint32_t const depth;
    uint32_t hiwat;
}
  • 销毁自动发布池
对AutoreleasePoolPage里存储的所有对象依次从后往前调用release
直到遇到对象POOL_BOUNDARY,表明当前Autorelease Pool中的对象已经被全部释放。

void
objc_autoreleasePoolPop(void *ctxt)
{
    AutoreleasePoolPage::pop(ctxt);
}
  • AutoReleasePool总结
  1. autorelease Pool是由多个AutoreleasePoolPage对象以双向链表的方式组织起来的数据结构。

  2. 每个AutoreleasePoolPage只能存储有限个对象指针。当新的对象加入Autorelease Pool的时候,如果当前的AutoreleasePoolPage存储空间不足,会新初始化一个AutoreleasePoolPage,加入到链表末端。

  3. Autorelease Pool可以被嵌套创建。创建一个新的Autorelease Pool的时候,会在当前AutoreleasePoolPage中插入边界对象POOL_BOUNDARY,以和上一个Autorelease Pool以区别。

  4. 当Autorelease Pool销毁的时候,对AutoreleasePoolPage里存储的所有对象依次从后往前调用release,直到遇到对象POOL_BOUNDARY,表明当前Autorelease Pool中的对象已经被全部释放。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,252评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,886评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,814评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,869评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,888评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,475评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,010评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,924评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,469评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,552评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,680评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,362评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,037评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,519评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,621评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,099评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,691评论 2 361