OC自动释放池

自动释放池:出释放池,池内对象快速释放

防⽌内存在短时间内暴涨

大内存的图片->自动释放池使用,图片能快速释放

@autoreleasepool {  }

汇编调试:

调用:objc_autoreleasePoolPush 和 objc_autoreleasePoolPop

objc_autoreleasePoolPush -> AutoreleasePoolPage::push()

AutoreleasePoolPage 的数据结构

class AutoreleasePoolPage;

struct AutoreleasePoolPageData

{

magic_t const magic; ⽤来校验 AutoreleasePoolPage 的结构是否完整

__unsafe_unretained id *next; 指向最新添加的 autoreleased 对象的下⼀个位置,初始化时指向begin() , AutoreleasePoolPage是一个栈,栈顶指针是next

pthread_t const thread; 指向当前线程

AutoreleasePoolPage * const parent; 指向⽗结点,第⼀个结点的 parent 值为 nil,Page 与 Page 之间 是通过双向链表连接的

AutoreleasePoolPage *child; 指向⼦结点,最后⼀个结点的 child 值为 nil 

uint32_t const depth; 代表深度,从 0 开始,往后递增 1。即双向链表的长度

uint32_t hiwat; 代表 high water mark 最⼤⼊栈数量标记

    ...

}

AutoreleasePoolPage::push() -> autoreleaseFast(POOL_BOUNDARY) ->

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);

        }

    }

当前正在添加对象的Page 为热页,其他Page为冷页

Page 存在并且Page存的对象没有满(504个) -> page->add(obj)

Page 存在并且Page存的对象已经满 ->  autoreleaseFullPage(obj, page) 双向链表新创建一个节点(页),并和传入的Page关联

Page 不存在 -> autoreleaseNoPage(obj); 创建新页

autoreleaseNoPage -> setHotPage -> page->add(POOL_BOUNDARY) -> page->add(obj)

示意图

出自动释放池 -> objc_autoreleasePoolPop

创建对象时 alloc new copy 不会添加到Page中的,

+ (id)person{

    return [Person new];

}

+ (id)person_2 {

    return [[Person alloc]init];

}

不同的创建方式才可以添加进去

    @autoreleasepool {

        Person*obj = [Personperson];

        NSLog(@"%@", obj);

        _objc_autoreleasePoolPrint();

    }

lldb调试

autoreleasepool中的变量出自动释放池就会释放,可以嵌套

⾃动释放池和runloop的关系

App启动后,苹果在主线程 RunLoop ⾥注册了两个 Observer其回调都是_wrapRunLoopWithAutoreleasePoolHandler()。

1. Observer 监视的事件是 Entry(即将进⼊Loop),其回调内会调⽤_objc_autoreleasePoolPush() 创建⾃动释放池。其 order 是-2147483647,优先级最⾼,保证创建释放池发⽣在其他所有回调之前。

2. Observer 监视了两个事件: BeforeWaiting(准备进⼊休眠) 时调⽤_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的池并创建新池;Exit(即将退出Loop) 时调⽤ _objc_autoreleasePoolPop() 来释放⾃动释放池。这个 Observer 的 order 是2147483647,优先级最低,保证其释放池发⽣在其他所有回调之后。

⾃动释放池 与线程关系:每一个线程会创建一个动释放池

在ARC环境下,autorelease 对象(不是new alloc...创建的)在什么时候释放?

1. ⼿动添加到@autoreleasepool⾥⾯的autorelease对象,是在出了@autoreleasepool的作⽤域之后被释放。

2. 主线程:由RunLoop控制,会在每⼀次的RunLoop循环结束时释放

3. 子线程:开启RunLoop,由RunLoop控制。不开启RunLoop在⼦线程销毁的时候释放

你可能感兴趣的:(OC自动释放池)