美文网首页
iOS AutoreleasePool

iOS AutoreleasePool

作者: CrystalZhu | 来源:发表于2020-02-23 17:11 被阅读0次

    AutoreleasePool(自动释放法)在OC中的一种内存自动回收机制,它可以延迟加入AutoreleasePool中的变量release的时机.在正常情况下,创建的变量会在超出其作用域的时候release,但是如果将变量加入AutoreleasePool,那么release将延迟执行.

    AutoreleasePool创建和释放

    1. app启动后,苹果在主线程RunLoop里注册了两个Observe,其回调都是_wrapRunLoopWithAutoreleasePoolHandler().
    2. 第一个Observe监视的事件是Entry(即将进入loop),其回调内会调用_objc_autoreleasePoolPush()创建自动释放池,其order是-2147483647,优先级最高,保证创建释放池发送在其他回调之前
    3. 第二个Observer监视了两个事件:BeforeWaiting(准备进入休眠)时调用_objc_autoreleasePoolPop()和_objc_autoreleasePush()释放旧的池并创建新的池,Exit(即将退出Loop)时调用_objc_autoreleasePoolPush()来释放自动释放池这个Observer的order是2147483647,优先级最低,保证其释放池发生在其他回调之后.
    4. 在主线程执行的代码,通常是写在诸如事件回调,Timer回调内的,这些回调会被RunLoop创建好的autorelease环绕着,所以不会出现内存泄露,开发者也不必显式创建pool了

    也就是说AutoreleasePool创建是在一个RunLoop事件开始之前(Push),AutoreleasePool释放是在一个RunLoop事件即将结束之前(Pop).

    AutoreleasePool里的Autorelease对象的加入是在RunLoop事件中,AutoreleasePool里的Autorelease对象的释放是在AutoreleasePool释放时.

    用途: 苹果官方文档说:
    ①如果你编写的程序不是基于UI框架,比如说命令行工具;
    ②如果是你编写的循环中创建了大量的临时对象;
    ③如果你创建了一个辅助线程.

    官方提供的Demo:

    NSArray *urls = <# An array of file URLs #>;
    for (NSURL *url in urls){
      @autoreleasepool{
        NSError * error;
        NSString * fileContents = [NSString stringWithContentsOfURL: url encoding: NSUTF8StringEncoding error: &error];
        /* Process the string, creating and autoreleasesing more objects. */
      }
    }
    

    这里写了一个Demo,测试使用autoreleasepool的内存占用情况
    加了@autoreleasepool内存稳定在73M,不使用autoreleasepool的会出现暴增的情况,所以autoreleasepool还是挺有用的

    static const int kStep = 50000;
    static const int kIterationCount = 10 * kStep;
    //查看app运行内存
    -(void)obserMemoryUsage{
      NSNumber *num = nil;
      NSString *str = nil;
      for (int i=0; i<kIterationCount; i++){
        @autoreleasepool{
          num = [NSNumber numberWithInt: i];
          str = [NSString stringWithFormat:@"test"];
          [NSString stringWithFormat: @"%@%@", num, str];
          if (i%kStep == 0){
            double ff = getMemoryUsage();
            NSLog(@"%f", ff);
          }
        }
      }
    }
    
    double getMemoryUsage(void){
      struct task_basic_info  info;
      mach_msg_type_number_t size = sizeof(info);
      kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
      double memoryUsageInMB = kerr == KERN_SUCCESS ? (info.resident_size/1024.0/1024.0) : 0.0;
      return memoryUsageInMB;
    }
    

    相关文章

      网友评论

          本文标题:iOS AutoreleasePool

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