优化iOS的内存-自动释放池

问题:项目中我们经常遇到一种情况,因为某个功能需要创建很多临时变量,而且这些变量比较耗内存,还会造成崩溃。比如下面是渲染视频每一帧的代码,很耗内存,而且上限不可控,乃至崩溃:

    //写入时的逻辑:将数组中的每一张图片多次写入到buffer中,
    while([writerInput isReadyForMoreMediaData]){
        CVPixelBufferRef buffer =NULL;
        if (frame < frameCount) {
            UIImage *frameImage = [export getImageWithCurrentFrame:frame];
            CGImageRef imageRef = frameImage.CGImage;
            // 裁剪
            CGImageRef subImageRef = CGImageCreateWithImageInRect(imageRef, self.svgaCropRect);
            // 将图片转成buffer
            buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:subImageRef withBottomCGImage:bottomCGImage];
            CGImageRelease(subImageRef);
            if(buffer){
                //添加buffer并设置每个buffer出现的时间,每个buffer的出现时间为第n张除以60(20是一秒20张图片,帧率,也可以自己设置其他值)所以为frame/60,即CMTimeMake(frame,60)为每一个buffer出现的时间点
                CLog(@"frame = %d", frame);
                if(frame >=0&&![adaptor appendPixelBuffer:buffer withPresentationTime:CMTimeMake(frame, DEVideoFrame)]){//设置每秒钟播放图片的个数
                    // NSLog(@"FAIL");
                }else{
                    // NSLog(@"OK");
                }
                CFRelease(buffer);
            }

分析下原因:
采用ARC内存管理,frameImage对象占用内存没有及时释放,循环创建,飙升过高造成崩溃。
解决方案:
虽然我们不能直接对frameImage进行release操作,但我们可以引入自动释放池(AutoreleasePool),

@autoreleasepool {
 // Code benefitting from a local autorelease pool.
}

循环内引入,

            @autoreleasepool {
                UIImage *frameImage = [export getImageWithCurrentFrame:frame];
                CGImageRef imageRef = frameImage.CGImage;
                // 裁剪
                CGImageRef subImageRef = CGImageCreateWithImageInRect(imageRef, self.svgaCropRect);
                // 将图片转成buffer
                buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:subImageRef withBottomCGImage:bottomCGImage];
                CGImageRelease(subImageRef);

增加@autoreleasepool后,自动释放了临时创建的对象内存,内存没有没有明显的上涨。
拓展:
看下入口main函数,

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

源码如图:


main函数

@autoreleasepool的底层代码__AtAutoreleasePool __autoreleasepool__AtAutoreleasePool是一个结构体。

struct __AtAutoreleasePool {
  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
  void * atautoreleasepoolobj;
};

__AtAutoreleasePool __autoreleasepool;相当于执行了__AtAutoreleasePool的构造函数和析构函数

atautoreleasepoolobj = objc_autoreleasePoolPush();
objc_autoreleasePoolPop(atautoreleasepoolobj);

push是Page执行,pop同理

void *
objc_autoreleasePoolPush(void)
{
    return AutoreleasePoolPage::push();
}

Page继承自PageData

Page

PageData如下:
PageData

结论:分析PageData结构体,看出autoreleasepool是一个对Page进行分页管理的双向链表。分析push和pop方法(引文在下方)得出,每一个autoreleasepool对象只有一个哨兵,哨兵放在第一页中;每一页的大小为4096字节;每一页的前56个字节存储页的AutoreleasePoolPageData结构体数据;第一页的第56往后8个字节存储哨兵,后面存储autorelease对象,总共可以存储504个;从第二页开始,每页可以存储505个对象;objc_autoreleasepoolpush是一个查找child,递增next,创建新页的过程;objc_autoreleasepoolpop是一个查找parent,递减next,释放对象,销毁page的过程,遇到哨兵对象即停止。

引文:https://zhuanlan.zhihu.com/p/321687906?utm_id=0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容