2

给令人头疼的内存和崩溃问题一个解决思路 - SwiftCafe 享受代码的乐趣

 3 years ago
source link: http://www.swiftcafe.io/post/mem-profiler
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

给令人头疼的内存和崩溃问题一个解决思路 - SwiftCafe 享受代码的乐趣

给令人头疼的内存和崩溃问题一个解决思路

swift 发布于 2020年12月18日 内存问题

随着我们工程的体量增长,代码结构变得越来越复杂。这时候很多内存问题就变得越来越难解决。一个不小心的循环引用就会导致一部分内存被一直占用。而这样的内存泄露一般都会随着代码量的增长不断的引入到项目中。往往到了最后,这个问题就不了了之了。

还好现在手机的内存越来越大,但即使这样,当你的工程越来越大之后,这些不断引入的内存问题,一定会对你应用的稳定性有越来越多的影响。

FBMemoryProfiler

正因为这样的问题,今天给大家介绍 Facebook 的一个开源库 FBMemoryProfiler。 https://github.com/facebook/FBMemoryProfiler

我们应用中导致内存泄露的元凶大多是循环引用。 所谓循环引用就是几个实例互相使用 strong 引用对方,最后导致谁也释放不掉谁。

FBMemoryProfiler 是几个组件的结合。其中包括 FBAllocationTracker 和 FBRetainCycleDetector。

FBAllocationTracker 用于检测应用在运行时所有实例的分配。它的原理其实就是用 method swizzling 替换原本的 alloc 方法。这样就可以记录下所有的实例分配了。使用起来也不难,在工程的 main 函数中初始化:

#import <FBAllocationTracker/FBAllocationTrackerManager.h>

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/FBMemoryProfiler.h>

FBMemoryProfiler *memoryProfiler = [FBMemoryProfiler new];
[memoryProfiler enable];

// Store memory profiler somewhere to extend it's lifetime
_memoryProfiler = memoryProfiler;

然后启动应用,完整的内存报告就展示出来了:

1.gif

总结

FBMemoryProfiler 除了可以这样手动调试之外,它还可以进行自动化检测。 通过它内置的两个组件 FBRetainCycleDetector 和 FBAllocationTracker,直接检测出内存中的循环引用,然后把数据发送到自己的服务器上,可以形成一个自动化检测系统。 Facebook 有一篇文章专门介绍这个,大家感兴趣也可以研究一下 https://code.facebook.com/posts/583946315094347/automatic-memory-leak-detection-on-ios/。 如果你需要对内存引用做深入的优化,这个工具应该能够帮到你。

FBMemoryProfiler 的 Github 主页: https://github.com/facebook/FBMemoryProfiler

如果你觉得这篇文章有帮助,还可以关注微信公众号 swift-cafe,会有更多我的原创内容分享给你~

本站文章均为原创内容,如需转载请注明出处,谢谢。
qrcode.jpg 关注微信公众号
发现更多精彩
swift-cafe


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK