一、概要
Instruments 是目前Mac OS X 和 iOS开发最强大的性能优化工具,提到Instruments自然会联想到处理内存问题,但它不仅仅局限于此,Instruments包含以下功能:
1、分析程序进程行为
2、分析内存分配及释放细节
3、查找CPU问题
4、查找程序性能瓶颈
5、自动化测试代码
虽然iOS5引入了ARC内存管理机制,但实际项目中对象之间引用复杂,循环引用引起内存泄漏仍然难以解决,这个时候就需要真正的掌握程序的行为,然后找出问题所在,这些都可以使用Instruments解决。
二、本文重点
借助Instruments分析程序的内存分配及泄漏
Instruments使用起来并不难,但问题在于工具默认设置的无法正确工作,如果重新配置后就会发现这是个很给力的工具,能很快的找出项目中存在的问题,本文通过以上两个重点来描述Instruments的入门技巧,让更多新手熟悉并使用Instruments。
三、Instruments入门
1、借助Instruments分析程序的内存分配与释放
1)分析内存分配
新建一个项目,合适位置添加如下代码(对有一点iOS开发经验都可以搞定)
这段代码会定时2秒不断的创建UIView
- (void) leakMethd { for (int i = 0; i< 100; i++) { UIView *aView = [[UIView alloc] init]; } } - (void)viewDidLoad { [super viewDidLoad]; [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(leakMethd) userInfo:nil repeats:YES]; }
选择 Allocations工具,点击Profile,这时模拟器会启动,并且Instruments界面如下
很显然,程序的内存使用正在不停的快速增长,假设我们不知道之前我们在工程中添加了哪些代码,现在就用Instruments分析程序可能出现的问题:
程序运行一段时间后,如图:
All Heap Allocation是总共分配多少内存
Live Bytes 是各个部分占用了多少内存
Living 分配的对象数量
程序从堆上总共分配了12.55MB空间,但UIView就占了5.48M,这很可疑,然后点击UIView后的小箭头:
并且打开Extended Detail
看到UIVIewController leakMethod方法很可疑,于是点击右边的方法,可以进入代码实现页面:
找到问题代码了,100.0%的意思是这行代码分配当前的内存,可以点击上图绿框中的设置按钮,来设置分析数据显示的格式:
修改成View as Value,可以显示具体分配了多少内存。点击Refresh会重新刷新数据,更新到当前分配了多少内存。
如果感觉这样分析还不够明显,特别是对象之间调用关系非常复杂的时候,还可以浏览Call Trees,这样切换到Call Trees
但此时看到是这样的,根本找不到直接有用的信息:
不要以为这个功能不给力,其实很给力,但需要配置一下(上图绿色框的那部分),以下是各个配置的功能说明:
Separate by Thread: 每个线程应该分开分析,以便找出哪些大量占用CPU的"重"线程
Invert Call Tree: 从第0帧开始取样,这样可以看到CPU中耗时间时间最深的方法.也就是说FuncA{FunB{FunC}} 勾选此项后堆栈以C->B-A 把调用层级最深的C显示在最外面
Hide Missing Symbols: 如果dSYM无法找到你的app或者系统框架的话,那么表中看不到方法名只能看到十六进制的数值,如果勾线此项可以隐藏这些符号,便于简化数据,更有利于分析
Hide System Libraries: 勾选此项你会过滤掉系统调用而显示你的调用,因为通常你只关心cpu花在自己代码上的时间不是系统上的
Show Obj-C Only: 只显示oc代码 ,如果你的程序是像OpenGl这样的程序,不要勾选侧向因为他有可能是C++的
Flatten Recursion: 递归函数, 每个堆栈跟踪一个条目
Top Functions: 一个函数花费的时间直接在该函数中的总和,以及在函数调用该函数所花费的时间的总时间。因此,如果函数A调用B,那么A的时间报告在A花费的时间加上B.花费的时间,这非常真有用,因为它可以让你每次下到调用堆栈时挑最大的时间数字,归零在你最耗时的方法。
这下清晰多了,而且很容易的找到了方法调用轨迹,双击方法可以进入代码实现,工具会告诉哪行代码都分配了多少内存:
工具栏的另外几个功能可以自己去研究:
2)分析内存泄漏
分析内存泄漏使用Leaks工具,打开方式Product -> Profiler,或者快捷键 Cmd + i,然后选择Leaks工具:
选择 Call Trees ,并修改配置
双击,进入泄漏的方法:
这样就能定位泄漏的位置了。
注意:内存泄漏一般分两种
第一种:一个对象尚未被释放,但是不再被引用的了
第二类:内存分配,永远不会有机会被释放(循环引用)
以上分析方法都是针对第一种情况内存泄漏,通过观察内存分配与内存释放来定位问题。当然,内存问题分析还不仅仅如此,还有很多方面可以深入,以后再研究了。