iOS 使用Instruments优化内存性能

iOS 使用Instruments优化内存性能ios

问题

项目中使用到图片合成视频,发现内存增加十分的迅速,致使一些由于内存引发的问题,本文使用这个案例,结合Instruments工具检测和分析问题,最终解决内存问题。git

本文的Demo代码 ScreenRecorderTest2app

Instruments检测

查看某个范围内的内存增加ide

  1. 打开Instruments选择Allocations工具,点击录制按钮进行录制
  2. 使用鼠标框选出内存增加的区域,图中两条黑线中的高亮区域

查看某个范围内的内存增加函数

  • 上面图表区域是内存的可视化视图
  • 下面的面板区域显示的是具体的统计数据
    能够看到总体的内存增加为16.81M (All Heap Allocations 堆内存的分配)

堆内存分配的详细统计数据
点击All Heap Allocations旁边的小箭头按钮能够看堆内存分配的详细统计数据: 堆内存分配的详细统计数据工具

  • Address:数据的内存地址
  • Timestamp:数据建立的时间
  • Size:数据的大小
  • Responsible Library:数据建立的相关的库
  • Responsible Caller:数据建立的相关的库的函数调用

统计数据表中能够看出AppleJPEG 库调用 applejpeg_decode_create 方法建立了不少的内存的数据

 右边区域显示的是函数的调用栈信息面板(Stack Trace),右上角的工字型按钮能够切换显示系统函数调用
切换显示系统函数调用性能

内存分配大小与对应的代码调用信息的可视化显示
点击调用栈中的高亮代码能够查看代码详情和内存信息:
内存分配大小与对应的代码调用信息的可视化显示优化

右边的标注区域显示的是内存占用的比例。code

分析

上图中看到buffer对象和image占用的内存最大,可是buffer在每次使用以后都会调用CVPixelBufferRelease释放对应的内存,不会有内存的问题,image对象释放的不及时,会在整个while循环块中保留一段时间,致使内存的增加。
此外image对象释放不及时和在在同一时间调用CVPixelBufferRelease(buffer);释放buffer也有关系,若是没有建立buffer和释放buffer的操做,image对象的增加也不会很明显,释放的速度也挺快,下面两个对照组能够进行对比分析视频

对照组1:只有在循环中建立image对象内存增加:
内存增加为2.73M
对照组1:只有在循环中建立image对象内存增加:

对照组2:在循环中添加autoreleasepool建立image对象内存增加:
内存增加为492K
对照组2:在循环中添加autoreleasepool建立image对象内存增加

由上可知,使用autoreleasepool能够有效的解决在某个循环中建立大量的内存敏感型对象致使的内存上涨的问题

最终解决方案
在while循环内部使用autoreleasepool块,每次循环arc对象得以及时的释放,内存增加从原来的16.81M降低到了只有475K
最终解决方案

代码:

while(i < imageNames.count) {
    // 添加自动释放池,让内存敏感型的对象(UIImage)及时释放
    @autoreleasepool {
       // 代码省略...
        NSString *imageName = [imageNames objectAtIndex:i];
        NSString* imagePath = [imageSavedDir stringByAppendingPathComponent:imageName];
        UIImage* image = [UIImage imageWithContentsOfFile:imagePath];
        if(adaptor.assetWriterInput.readyForMoreMediaData) {
            i++;
            CMTime frameTime = CMTimeMake(1, fps);
            CMTime lastTime = CMTimeMake(i, fps);
            CMTime presentTime = CMTimeAdd(lastTime, frameTime);
            
            buffer = [self pixelBufferFromCGImage:[image CGImage] size:videoFrameSize];
            // 写入视频
            BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
            if(buffer) {
                CVPixelBufferRelease(buffer);
            }
            // 代码省略...
            [NSThread sleepForTimeInterval:0.05];
        } else {
            NSLog(@"Error: Adaptor is not ready");
            [NSThread sleepForTimeInterval:0.05];
            i--;
        }
    }
}

总结

以上是使用Instruments解决内存问题的总结,若有不妥之处还请不吝赐教
本文的Demo代码 ScreenRecorderTest2

相关文章
相关标签/搜索