前言介绍:
或许很多朋友对 Instruments 应用不太了解,但可能很多老的 iOS 开发者都应该用过 Instruments 工具来检测 iOS 应用内存泄漏情况。特别是在 iOS 5.0 之前,即苹果在iOS 平台上面还没支持 ARC 的时候,写 iOS 应用就类似 C 语言那样,容易忘记释放内存,而内存对移动设备而言是非常可贵的。即使目前 iPhone 设备内存已经满足 512MB 了,但是因为苹果的后台模式是把整个应用封装起来等待下次启用,所以该应用所占用的内存同样被占据了。也就是即使应用进入后台模式,它还是仍然占用原先的内存的,所以你打开的应用越多,内存耗用自然也很多。对很多普通用户而言,往往他们打开的应用都是进入后台模式的,很少有用户清理后台的应用,所以也就造成很多应用其实可用内存还是非常有限地 (题外话:如果苹果原生支持一键清理后台程序就好了,貌似越狱的工具里面有这样的支持的。
还有做过 iOS 应用自动化测试的开发者,应该对UIAutomation 很熟悉吧。它就是通过 JS 脚本来写界面自动化测试用例。而 Instruments 应用对 UIAutomation 支持很完善,你可以通过它查看很多代码潜在的问题,并测试性能。
其实 Instruments 应用还有很多强大的功能,它原生支持很多 instrument 工具,帮助你分析你的代码,不仅包括内存检测和自动化测试,它还可以监测文件读写操作等等。所以一个好的 iOS 开发者是应该掌握 Instrument 应用的使用。因为 Instruments 应用本身功能太强大的,所以完全掌握机会不可能,但是因为它们内置的很多工具具有相似性,所以基本掌握自己常用的即可。同时了解一下内部有哪些功能,这样在你需要用到的时候再查查文档,就可以很快上手了。
正文 Instruments 的介绍:
Instruments 是一个很灵活的、强大的工具;是性能分析、动态跟踪 和分析 OS X 以及 iOS 代码的测试工具;用它可以极为方便收集关于一个或多个系统进程的性能和行为的数据,并能及时随着时间跟踪而产生的数据,并检查所收集的数据,还可以广泛收集不同类型的数据;也可以追踪程序运行的过程,这样 instrument 就可以帮助我们了解用户的应用程序和操作系统的行为。
总结一下 instrument 能做的事情:
1.Instruments 是用于动态调追踪和分析 OS X 和 iOS 的代码的性能分析和测试工具;
2.Instruments 支持多线程的调试;
3.可以用 Instruments 去录制和回放,图形用户界面的操作过程
4.可将录制的图形界面操作和 Instruments 保存为模板,供以后访问使用。
或者说:
1.追踪代码中的(甚至是那些难以复制的)问题;
2.分析程序的性能;
3.实现程序的自动化测试;
4.部分实现程序的压力测试;
5.执行系统级别的通用问题追踪调试;
6.使你对程序的内部运行过程更加了解。
介绍几个常用的 instrument 工具:
Leaks(泄漏):一般的查看内存使用情况,检查泄漏的内存,并提供了所有活动的分配和泄漏模块的类对象分配统计信息以及内存地址历史记录;
Time Profiler(时间探查):执行对系统的 CPU上运行的进程低负载时间为基础采样。
Allocations(内存分配):跟踪过程的匿名虚拟内存和堆的对象提供类名和可选保留/释放历史;
Activity Monitor(活动监视器):显示器处理的 CPU、内存和网络使用情况统计;
Blank(空模板):创建一个空的模板,可以从 Library 库中添加其他模板;
Automation(自动化):这个模板执行它模拟用户界面交互为 iOS 手机应用从 instrument 启动的脚本;
Core Data:监测读取、缓存未命中、保存等操作,能直观显示是否保存次数远超实际需要。
Cocoa Layout:观察约束变化,找出布局代码的问题所在。
Network:跟踪 TCP/IP 和 UDP/IP 连接。
Automations:创建和编辑测试脚本来自动化 iOS 应用的用户界面测试。
Instruments 常用的三大类:
Leaks:找到引发内存泄漏的起点
Time Profiler:分析代码的执行时间,找出导致程序变慢的原因
Allocations:监测内存使用/分配情况
一、使用 Instruments 的 Leaks工具
[ˈɪnstrʊm(ə)nt] [liks 漏洞]
迅速膨胀的内存可以很快让程序毙命,所以要多加防范。即使有 ARC(自动引用计数)内存管理机制,但在现实中对象之间引用复杂,循环引用导致的内存泄漏仍然难以避免,所以关键时刻还要自力更生。分析内存泄露不能把所有的内存泄露查出来,有的内存泄露是在运行时,用户操作时才产生的。那就需要用到 Instruments 的leaks 了。
Leaks 调试解决 iOS 内存泄漏的工具 快捷键:command + control + i
打开步骤:
首先我们选中 Xcode先把模拟器(command + R)运行起来
然后我们再选中 Xcode,按快捷键(command + control + i)运行起来, 选择 Leaks --> Choose
之前的
2018-08-23
没有明显变化,如果这些工具不够可以自行添加
或者 点击 Xcode 的 “调试导航”
然后选中 “Memory”,再点击右侧的 “Profile in Instruments”,
会自动打开 Instruments。这时候会弹出来一个对话框,
选择 “Transfer” 这种方式打开
在或者你可以通过 Xcode --> Open Developer Tool --> instruments --> Leaks 的方式来打开
再或者你可以 按着 control+空格键,输入instruments 打开 (meishichulaihaha)
打开后,这时界面如图 <老版本的>:
由于 Leaks 是动态监测,所以我们需要手动操作 APP,进行测试,一边操作 APP,一边观察 Leaks 的变化,在暂停按钮的右边 我们可以选择正在 运行的程序 & 选择设备 & App, 之后点击 红点 Record(红色圆圈按钮)运行。
观察,如果发现在 Leaks 里面有一个 红色X,这说明了我们的 APP 存在内存泄露。
点击暂停,点击其中一个,然后我们开始分析。(也可继续检测,当多个时暂停,一次处理了多个)
下面就是定位修改了, 此时选中有红色叉的 Leaks,下面有个田Leaks 字方格,点开,选中 Call Tree。
接着就是最关键的一步,在这个界面的右下角有若干选框,选中Invert Call Tree 和 Hide System Libraries,(红圈范围内)如果不知道在那个位置请接着往下看
定位
在详情面板选中显示的若干条中的一条,双击,会自动跳到内存泄露代码处,然后点击右上角 Xcode 图标进行修改。
Leaks界面讲解:
Leaks 启动后会开始录制,随着对模拟器运行的 App 的操作,可以在 Leaks 中查看内存占用的情况。
Leaks顶部分为两栏:Allocations (aləˈkeɪʃ(ə)n,分配 ) 和 Leaks,右侧的曲线代表内存分配和内存泄漏曲线。
点击第二栏 Leaks,如下图:
进行内存泄漏分析,右下角会出现Leaks调试的选项:
1、Record Settings (ˈrɛkɔːd 记录设置)
2、Display Settings 选项面板
3、Extended Detail 扩展面板(ɛkˈstɛnd,延展 diːteɪl,细节详情),在时间探查仪器的情况下,它是用来跟踪显示堆栈。
老版本是在右边显示:
现在已经改为:
之前说过,新本版做了改变,需要先选择 Call Tree
内存泄漏动态分析技巧:
1.在 Display Settings 界面建议把 Snapshot Interval (snapʃɒt, 数据快照)间隔时间设置为10秒,勾选Automatic Snapshotting,Leaks 会自动进行内存捕捉分析。(新版本直接在底部修改)
2.熟练使用 Leaks 后会对内存泄漏判断更准确,在可能导致泄漏的操作里,在你怀疑有内存泄漏的操作前和操作后,可以点击 Snapshot Now 进行手动捕捉。
3.开始时如果设备性能较好,可以把自动捕捉间隔设置为 5 秒钟。
4.使用ARC的项目,一般内存泄漏都是 malloc、自定义结构、资源引起的,多注意这些地方进行分析。
5.开启ARC后,内存泄漏的原因
开启了ARC并不是就不会存在内存问题,苹果有句名言:ARC is only for NSObject。
注:如果你的项目使用了ARC,随着你的操作,不断开启或关闭视图,内存可能持续上升,但这不一定表示存在内存泄漏,ARC释放的时机是不固定的。
做一下就简单的演示:
项目:
创建 single View App
添加一个People 类
这里选用的是MRC :
在 Main.storyboard 里拖了一个 button 并且为 button的 “touchUpInset”事件绑定 buttonClick:事件处理方法
在 People.h 文件里面代码如下
#import@interfacePeople:NSObject@property(nonatomic,assign)NSString*str;@end
在 UIViewController.m 文件里面代码如下:
-(IBAction)buttonClick:(id)sender{People*people=[[People alloc]init];[people retain];people.str=@"1324567";}
运行项目,切换到 iOS 模拟器,点击那个测试按钮多点几次 “button”,
切换到 Instruments 会发现 如果没有泄漏 如图
当然这里是泄漏,在 “Leaks” 一栏里有红色的 X。如图这就是内存泄露了。
点击暂停,然后点击 “Leaks” 一栏
然后点击“导航栏”切换到“call tree”模式下
看到列表里列出了内存泄露的调用逻辑:
注意:
在老版本中:
需要勾选右边的详细窗口 Display Settings 中的 Call Tree 中Separate by Thread和Hide System Libraries两个选项,
Hide System Libraries作用是隐藏系统函数。如果不点击 这里显示的是执行代码完整路径,其中系统和应用本身一些调用路径完全揉捏在一起. 完全看不到我们关心的应用程序中实际代码执行耗时和代码路径实际所在位置
不勾选效果如下:
勾选效果如下:
在新的版本中 Call Tree 的 这些设置换了位置 在底部左下角:
勾选之后,双击一下就会来到内存泄漏的地方
这里对 Display Settings 中 的Call tree选项做一下说明 [官方user guide翻译]:
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的消耗情况
选择 Detail -> Call Tree
表示查看整个调用过程有了上面的基础知识就可以对App的CPU消耗情况进行实时检测了。
问题分析
首先 由于 Leaks 是动态监测,所以我们需要手动操作 APP,进行测试,一边操作 APP,一边观察 Leaks 的变化。
也就是说两者必须关联好,最为简单的方法就是:
问题一
leaks->Call Tree->Call Tree-> 指针地址界面,右上角栏目xcode图标是灰色的,不能用?设置齿轮图标也是灰色的?
回复:我自己复现了一下该情况 正常情况下:
注意我这里是 Run 1 of 1 若果是其它的 Run 1 of 2/3/4... & Run 2/ 3 of 2 就不可以点击了。
问题二
UIAutomation 在哪里?Instruments 里面没有?
回复:目前没有了,或者使用老的版本 或者使用 UITests
作者:时苒君
链接:https://www.jianshu.com/p/92cd90e65d4c
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
网友评论