美文网首页
iOS ARC + AutoReleasePool 实现机制

iOS ARC + AutoReleasePool 实现机制

作者: iOS小童 | 来源:发表于2019-12-13 16:31 被阅读0次

    自动引用计数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中的对象已经被全部释放。

    相关文章

      网友评论

          本文标题:iOS ARC + AutoReleasePool 实现机制

          本文链接:https://www.haomeiwen.com/subject/ymofnctx.html