应用开发到一定规模后,各种内存问题频频出现,还很难定位。你是否也体会过这种痛苦?
内存问题
随着我们工程的体量增长,代码结构变得越来越复杂。这时候很多内存问题就变得越来越难解决。一个不小心的循环引用就会导致一部分内存被一直占用。而这样的内存泄露一般都会随着代码量的增长不断的引入到项目中。往往到了最后,这个问题就不了了之了。
还好现在手机的内存越来越大,但即使这样,当你的工程越来越大之后,这些不断引入的内存问题,一定会对你应用的稳定性有越来越多的影响。
FBMemoryProfiler
正因为这样的问题,今天给大家介绍 Facebook 的一个开源库 FBMemoryProfiler。 github.com/facebook/FB…
我们应用中导致内存泄露的元凶大多是循环引用。 所谓循环引用就是几个实例互相使用 strong 引用对方,最后导致谁也释放不掉谁。
FBMemoryProfiler 是几个组件的结合。其中包括 FBAllocationTracker 和 FBRetainCycleDetector。
FBAllocationTracker 用于检测应用在运行时所有实例的分配。它的原理其实就是用 method swizzling 替换原本的 alloc 方法。这样就可以记录下所有的实例分配了。使用起来也不难,在工程的 main 函数中初始化:
#import
int main(int argc, char * argv[]) {
[[FBAllocationTrackerManager sharedManager] startTrackingAllocations];
[[FBAllocationTrackerManager sharedManager] enableGenerations];
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
然后在需要的时候调用 currentAllocationSummary 方法,就可以得到当前整体的实例分配情况:
NSArray<FBAllocationTrackerSummary *> *summaries = [[FBAllocationTrackerManager sharedManager] currentAllocationSummary];
有了 FBAllocationTracker, 我们可以记录应用中所有的示例分配。 但还需要另一个组件 FBRetainCycleDetector 才能完成循环引用的检测。
FBRetainCycleDetector 接受一个运行时的实例,然后从这个实例开始遍历它所有的属性,逐级递归。 如果发现遍历到重复的实例,就说明存在循环引用,并给出报告。
FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:myObject];
NSSet *retainCycles = [detector findRetainCycles];
NSLog(@"%@", retainCycles);
上面的代码初始化了 FBRetainCycleDetector 实例, 然后调用 addCandidate 方法添加要检测的实例。 然后调用 findRetainCycles 方法检测循环引用,并输出。
如果存在循环引用,就会输出类似的内容:
{(
(
"-> MyObject ",
"-> _someObject -> __NSArrayI "
)
)}
通过这个线索,你就可以找到你代码中可能导致循环引用的地方了。
两个基础组件介绍完了, 接下来就是 FBMemoryProfiler。 它其实内部调用的就是这两个组件,然后通过图形界面显示出来, 只需要这样调用,将 UI 界面展示出来:
#import
FBMemoryProfiler *memoryProfiler = [FBMemoryProfiler new];
[memoryProfiler enable];
// Store memory profiler somewhere to extend it's lifetime
_memoryProfiler = memoryProfiler;
然后启动应用,完整的内存报告就展示出来了:
总结
FBMemoryProfiler 除了可以这样手动调试之外,它还可以进行自动化检测。 通过它内置的两个组件 FBRetainCycleDetector 和 FBAllocationTracker,直接检测出内存中的循环引用,然后把数据发送到自己的服务器上,可以形成一个自动化检测系统。 Facebook 有一篇文章专门介绍这个,大家感兴趣也可以研究一下 code.facebook.com/posts/58394…。 如果你需要对内存引用做深入的优化,这个工具应该能够帮到你。
FBMemoryProfiler 的 Github 主页: github.com/facebook/FB…
如果你觉得这篇文章有帮助,还可以关注微信公众号 swift-cafe,会有更多我的原创内容分享给你~
本站文章均为原创内容,如需转载请注明出处,谢谢。