iOS 使用Instruments优化内存性能

淩亂°似流年 2022-10-01 10:46 325阅读 0赞

iOS 使用Instruments优化内存性能

问题

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

本文的Demo代码 ScreenRecorderTest2

Instruments检测

查看某个范围内的内存增长

  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),右上角的工字型按钮可以切换显示系统函数调用

切换显示系统函数调用

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

内存分配大小与对应的代码调用信息的可视化显示 

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

分析

上图中看到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

最终解决方案

代码:

  1. while(i < imageNames.count) {
  2. // 添加自动释放池,让内存敏感型的对象(UIImage)及时释放
  3. @autoreleasepool {
  4. // 代码省略...
  5. NSString *imageName = [imageNames objectAtIndex:i];
  6. NSString* imagePath = [imageSavedDir stringByAppendingPathComponent:imageName];
  7. UIImage* image = [UIImage imageWithContentsOfFile:imagePath];
  8. if(adaptor.assetWriterInput.readyForMoreMediaData) {
  9. i++;
  10. CMTime frameTime = CMTimeMake(1, fps);
  11. CMTime lastTime = CMTimeMake(i, fps);
  12. CMTime presentTime = CMTimeAdd(lastTime, frameTime);
  13. buffer = [self pixelBufferFromCGImage:[image CGImage] size:videoFrameSize];
  14. // 写入视频
  15. BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
  16. if(buffer) {
  17. CVPixelBufferRelease(buffer);
  18. }
  19. // 代码省略...
  20. [NSThread sleepForTimeInterval:0.05];
  21. } else {
  22. NSLog(@"Error: Adaptor is not ready");
  23. [NSThread sleepForTimeInterval:0.05];
  24. i--;
  25. }
  26. }
  27. }
  28. 复制代码

总结

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

转载于:https://juejin.im/post/5ca5d483f265da3097287049

发表评论

表情:
评论列表 (有 0 条评论,325人围观)

还没有评论,来说两句吧...

相关阅读

    相关 iOS instruments之Core Animation

    首先,感谢[这篇文章][Link 1]的作者,将文章分享出来。文章主要讲述一下几个问题: 1. 为什么要把控件尽量设置成不透明的,如果是透明的会有什么影响,如何检测这种影响

    相关 iOS instruments 介绍

    iOS instruments介绍 写代码的时候,我们时常需要借助一些工具来帮我们分析问题、找到问题,来达到调适和优化代码的目的。在iOS开发方面,XCode提供了一系列工具