工具篇- FBMemoryProfiler 内存泄漏的自动化排查
前言
应用开发到一定规模后,各种内存问题频频出现,还很难定位。你是否也体会过这种痛苦?随着我们工程的体量增长,代码结构变得越来越复杂。这时候很多内存问题就变得越来越难解决。一个不小心的循环引用就会导致一部分内存被一直占用。而这样的内存泄露一般都会随着代码量的增长不断的引入到项目中。手机设备的内存是一个共享资源。应用程序可能会不当的耗尽内存、崩溃,或者遭遇大幅度的性能降低。
还好现在手机的内存越来越大,但即使这样,当你的工程越来越大之后,这些不断引入的内存问题,一定会对你应用的稳定性有越来越多的影响。
现在已经存在一些开发者工具来辅助发现内存泄漏了,但是Xcode自带的工具并不好用,真的排查起来还是相对比较困难,因为很大的原因在于你并不清楚 App 到底在哪几个页面发生了泄漏!这样的人工排查与修复工程每次都得不断地重复操作。正因为如此,我们很难在迭代阶段早期就定位与修复内存问题。从代码书写初期就发现并解决掉
FBMemoryProfiler
很多同学说不知道怎么实时看自己 APP 的内存占用情况和内存泄漏的监测,下面介绍 Facebook 的一个开源库 FBMemoryProfiler。
内存检测.gif我们可以看到在页面跳转到TwoViewController 中时,我们可以看到FBMemoryProfiler可以捕捉到这个实例对象的存在,并且在TwoViewController页面销毁时,也发现这个实例对象也被销毁了。
我们在工程中新建文件的时候最好是工程总的文件都是项目简称开头,这样有利于我们的搜索筛选。
下面是一个使用FBMemoryProfiler 检测出循环引用造成的内存泄漏问题:
代码是这样的
@property (nonatomic, strong) NSTimer *timer;
@property(copy,nonatomic)NSString *name;
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(handleTimer)
userInfo:nil
repeats:YES];
- (void)handleTimer
{
self.name = @"123";
}
而且开发工具不会报任何警告
自动检测
FBMemoryProfiler 除了可以这样手动调试之外,它还可以进行自动化检测。 通过它内置的两个组件 FBRetainCycleDetector 和 FBAllocationTracker,直接检测出内存中的循环引用。
在客户端上自动进行内存泄漏监测实际上就是配合使用 FBRetainCycleDetector 加定时器或者在BaseViewController中使用,达到自动的效果。
#import <FBRetainCycleDetector/FBRetainCycleDetector.h>
FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:self];
NSSet *retainCycles = [detector findRetainCycles];
NSLog(@"%@", retainCycles);
像这样 把当前的ViewController 作为检测对象,如果当前的ViewController中存在循环引用的话就会自动打印出结果,类似下面的结果。我们可以根据结果找出问题所在。
{(
(
"-> MyObject ",
"-> _someObject -> __NSArrayI "
)
)}
这里要说一下,findRetainCycles查询方式所使用到的算法是DFS(深度优先搜索)。所以我们最好使用属性式的全局变量。详细了解FBRetainCycleDetector、FBRetainCycleDetector工作流程
顺便说一下,自动化检测中FBRetainCycleDetector是关键,所以,想要深入研究自动化检测的同学需要详细研究下FBRetainCycleDetector,网上文章还是挺多的。
小结
不论你是巨无霸 App 还是一个小型应用,良好的内存管理都是一个好的工程习惯。通过这些工具的帮助,我们能够更为便捷地去发现和修复内存泄漏的问题,让我们省下那些去手动检测的时间,更加聚焦在写出更好的代码上。
Reference:
http://www.cocoachina.com/ios/20160419/15954.html