iOS 使用Instruments优化内存性能ios
项目中使用到图片合成视频,发现内存增加十分的迅速,致使一些由于内存引发的问题,本文使用这个案例,结合Instruments工具检测和分析问题,最终解决内存问题。git
本文的Demo代码 ScreenRecorderTest2app
查看某个范围内的内存增加ide
函数
堆内存分配的详细统计数据
点击All Heap Allocations旁边的小箭头按钮能够看堆内存分配的详细统计数据: 工具
统计数据表中能够看出AppleJPEG 库调用 applejpeg_decode_create 方法建立了不少的内存的数据
右边区域显示的是函数的调用栈信息面板(Stack Trace),右上角的工字型按钮能够切换显示系统函数调用
性能
内存分配大小与对应的代码调用信息的可视化显示
点击调用栈中的高亮代码能够查看代码详情和内存信息:
优化
右边的标注区域显示的是内存占用的比例。code
上图中看到buffer对象和image占用的内存最大,可是buffer在每次使用以后都会调用CVPixelBufferRelease释放对应的内存,不会有内存的问题,image对象释放的不及时,会在整个while循环块中保留一段时间,致使内存的增加。
此外image对象释放不及时和在在同一时间调用CVPixelBufferRelease(buffer);释放buffer也有关系,若是没有建立buffer和释放buffer的操做,image对象的增加也不会很明显,释放的速度也挺快,下面两个对照组能够进行对比分析视频
对照组1:只有在循环中建立image对象内存增加:
内存增加为2.73M

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

由上可知,使用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