在开发过程中,有时我们会遇到内存泄漏的情况。苹果提供了一个强大Instruments工具来检测iOS应用内存泄漏情况。
以下对Instruments工具进行简单说明,通过实例演示检测内存泄漏的问题。
- Instruments工具
Instruments是用于动态调追踪和分析OS X和iOS的代码的性能分析和测试工具,支持多线程,可进行录制和回放,图形用户界面的操作过程。Instruments分析工具虽然很多,但是我们实际开发过程中并不能全部用到,下面简单接收几个常用的分析工具。
- Leaks(泄漏):一般的查看内存使用情况,检查泄漏的内存,并提供了所有活动的分配和泄漏模块的类对象分配统计信息以及内存地址历史记录;(内存检测是重点,在文章下面会详细演示说明)
- Time Profiler(时间探查):执行对系统的CPU上运行的进程低负载时间为基础采样。
- Allocations(内存分配):跟踪过程的匿名虚拟内存和堆的对象提供类名和可选保留/释放历史;
- Activity Monitor(活动监视器):显示器处理的CPU、内存和网络使用情况统计;
- Blank(空模板):创建一个空的模板,可以从Library库中添加其他模板;
- Automation(自动化):这个模板执行它模拟用户界面交互为IOS机应用从instrument启动的脚本;
- Core Data:监测读取、缓存未命中、保存等操作,能直观显示是否保存次数远超实际需要。
- Cocoa Layout:观察约束变化,找出布局代码的问题所在。
- Network:跟踪 TCP / IP和 UDP / IP 连接。
- Automations:创建和编辑测试脚本来自动化 iOS 应用的用户界面测试。
- Leaks(泄漏)
Leaks主要是查看内存使用情况,检查泄漏的内存,并提供了所有活动的分配和泄漏模块的类对象分配统计信息以及内存地址历史记录;
将工程ARC变更为MRC如下图:
创建类,声明对象:
#import <Foundation/Foundation.h> @interface Person : NSObject @property(nonatomic, assign) NSString *str; @end
模拟内存泄漏:
-(void)clickEvent{ Person *person = [[Person alloc] init]; [person retain]; person.str = @"test"; }
- 运行项目,切换到iOS模拟器,点击那个测试按钮多点几次“button”
- 切换到Instruments会发现 如果没有泄漏 如图
- 当然这里是泄漏,在“Leaks”一栏里有红色的 X。如图六这就是内存泄露了。
-
点击暂停,然后点击“Leaks”一栏
-
然后点击“导航栏”切换到“call tree”模式下
-
看到列表里列出了内存泄露的调用逻辑:
-
勾选之后,双击一下就会来到内存泄漏的地方
-
Separate By Thread:线程分离,只有这样才能在调用路径中能够清晰看到占用CPU最大的线程.每个线程应该分开考虑。只有这样你才能揪出那些大量占用CPU的"重"线程,按线程分开做分析,这样更容易揪出那些吃资源的问题线程。特别是对于主线程,它要处理和渲染所有的接口数据,一旦受到阻塞,程序必然卡顿或停止响应。
-
Invert Call Tree:从上到下跟踪堆栈信息.这个选项可以快捷的看到方法调用路径最深方法占用CPU耗时(这意味着你看到的表中的方法,将已从第0帧开始取样,这通常你是想要的,只有这样你才能看到CPU中话费时间最深的方法),比如FuncA{FunB{FunC}},勾选后堆栈以C->B->A把调用层级最深的C显示最外面.反向输出调用树。把调用层级最深的方法显示在最上面,更容易找到最耗时的操作。
-
Hide Missing Symbols:如果dSYM无法找到你的APP或者调用系统框架的话,那么表中将看到调用方法名只能看到16进制的数值,勾选这个选项则可以隐藏这些符号,便于简化分析数据.
-
Hide System Libraries:表示隐藏系统的函数,调用这个就更有用了,勾选后耗时调用路径只会显示app耗时的代码,性能分析普遍我们都比较关系自己代码的耗时而不是系统的.基本是必选项.注意有些代码耗时也会纳入系统层级,可以进行勾选前后前后对执行路径进行比对会非常有用.因为通常你只关心cpu花在自己代码上的时间不是系统上的,隐藏系统库文件。过滤掉各种系统调用,只显示自己的代码调用。隐藏缺失符号。如果 dSYM 文件或其他系统架构缺失,列表中会出现很多奇怪的十六进制的数值,用此选项把这些干扰元素屏蔽掉,让列表回归清爽。
-
Show Obj-C Only: 只显示oc代码 ,如果你的程序是像OpenGl这样的程序,不要勾选侧向因为他有可能是C++的
-
Flatten Recursion: 递归函数, 每个堆栈跟踪一个条目,拼合递归。将同一递归函数产生的多条堆栈(因为递归函数会调用自己)合并为一条。
-
Top Functions:找到最耗时的函数或方法。 一个函数花费的时间直接在该函数中的总和,以及在函数调用该函数所花费的时间的总时间。因此,如果函数A调用B,那么A的时间报告在A花费的时间加上B.花费的时间,这非常真有用,因为它可以让你每次下到调用堆栈时挑最大的时间数字,归零在你最耗时的方法。
-
需要添加其他工具的话:
- 关于界面的一些其他的补充:
- 左边的Show the CPU Data 可以查看每个CPU的消耗情况
- 中间的Show the Instruments Data 显示整体的消耗情况
- 右边的Show the Thread Data 可以查看每个线程对CPU的消耗情况