1.探索
首先通过
po [NSRunloop currentRunloop]
在控制台可以看到以下打印信息,发现runloop与autoreleasepool有关系
auto.png
我们可以推测,在触发obsever监听的时候,会处理autoreleasepool
order表示runloop处理的优先级
我们通过activities = 0xa0,可以监听autoreleasepool的处理
2.监听autoreleasepool
char autoreleaseActive = 0xa0; CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), autoreleaseActive, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { NSLog(@"_wrapRunLoopWithAutoreleasePoolHandler"); });
通过实践,在一次runloop的周期中大概会执行5次。
添加一个信号断点
屏幕快照 2018-05-09 上午11.30.32.png
发现在闲置状态(beforeWating)会不时进入这个断点
3.从runloop源码探究
auto2.png
虽然autoreleasepool的处理一直被触发,但是并没有唤醒休眠状态的runloop
4. autoreleasepool源码
提问:arc有必要使用autoreleasepool吗?
在mrc的时代,往往创建一个autoreleasepool对象
arc则使用
@ autoreleasepool
提问:arc下使用@ autoreleasepool 的意义?
首先执行下面两段代码作为对比
for (int i = 0; i < 1024*1024*30; i++) { @autoreleasepool { NSString *str = [NSString stringWithFormat:@"0123456789"]; }; }
for (int i = 0; i < 1024*1024*30; i++) { NSString *str = [NSString stringWithFormat:@"0123456789"]; }
结论:
第一段代码在会对内存进行优化,释放速度快;
第二段代码造成内存大量堆积,释放缓慢
通过clang解读@autoreleasepool源码
@autoreleasepool { NSString *str = [NSString stringWithFormat:@"0123456789"]; };
约等于
创建了一个autorelease对象 push autorelease NSString *str = [NSString stringWithFormat:@"0123456789"]; 释放掉autorelease(pop ~) clang
但是从clang出的源码中我们看不出释放,是因为autorelease的释放使用c++中的析构