转载

【高级iOS】autoreleasepool源码分析,并与runloop的关系

1.探索

首先通过

po [NSRunloop currentRunloop]

在控制台可以看到以下打印信息,发现runloop与autoreleasepool有关系

【高级iOS】autoreleasepool源码分析,并与runloop的关系

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次。

  • 添加一个信号断点

【高级iOS】autoreleasepool源码分析,并与runloop的关系

屏幕快照 2018-05-09 上午11.30.32.png

  • 发现在闲置状态(beforeWating)会不时进入这个断点

3.从runloop源码探究

【高级iOS】autoreleasepool源码分析,并与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++中的析构

正文到此结束
Loading...