美文网首页
autorelease的对象与@autoreleasepool

autorelease的对象与@autoreleasepool

作者: y浪淘沙y | 来源:发表于2018-12-06 16:48 被阅读10次

    首先,看两段代码执行之后,内存的变化:

    1、

    // 未使用@autoreleasepool
    for (int i = 0; i < 100000; i ++) {
            UIImage *img = [UIImage imageNamed:@"test.jpg"];
            NSLog(@"%@", @(i));
        }
    

    分析:imageName 返回的是 autorelease 的对象,因为我们一直处在循环中,因此它们将一直没有机会被释放。如果数量太多而且数据太大的时候,很容易因为内存不足而崩溃。若 for 循环中为 非autorelease 的对象,不会出现内存问题。
    如下图,我们可以看到内存占用情况:

    未使用@autoreleasepool.png

    2、

    // 使用@autoreleasepool
    for (int i = 0; i < 100000; i ++) {
            @autoreleasepool {
                UIImage *img = [UIImage imageNamed:@"test.jpg"];
                NSLog(@"%@", @(i));
            }
        }
    

    分析:这就涉及到 autorelease 的对象在什么时候释放的问题。
    引用【在没有手加Autorelease Pool的情况下,Autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop】。对于我们手动添加的@autoreleasepol{},显然出了它的作用域之后对象就会被release。这里我们每一次循环都生成了一个自动释放池,虽然可以保证内存使用达到最小,但是释放过于频繁也会带来潜在的性能忧虑。一个折中的方法是将循环分隔开加入自动释放池,比如每10次循环对应一次自动释放,这样能减少带来的性能损失。
    如下图,内存占用情况:

    使用@autoreleasepool.png

    什么时候用@autoreleasepool

    根据Apple的文档,使用场景如下:

    1. 写基于命令行的的程序时,就是没有UI框架,如AppKit等Cocoa框架时。
    2. 写循环,循环里面包含了大量临时创建的对象。(本文的例子)
    3. 创建了新的线程。(非Cocoa程序创建线程时才需要)
    4. 长时间在后台运行的任务。

    注:

    1、什么是autorelease 的对象?
    alloc、new、copy、mutableCopy四个内存管理的关键字,自身使用了这些关键字产生的对象都不是 autorelease 的对象,自身持有对象,那么不再需要时对象就会调用release方法释放对象;
    不是通过上面关键字产生的都是 autorelease 的对象,底层会将该对象注册到 autoreleasepool 中,不会立即释放,会在pool结束时,释放对象。
    2、参考
    iOS内存管理
    黑幕背后的Autorelease
    @autoreleasepool-内存的分配与释放

    相关文章

      网友评论

          本文标题:autorelease的对象与@autoreleasepool

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