iOS_ 性能优化_内存优化_Leaks工具的使用

<h3>内存优化:</h3>
Objective_C 有3种内存管理方法, 它们分别是 <b>MRR (Manual Retain Release, 手动保持释放), ARC(Automatic Reference Counting, 自动引用计数) 和 GC(Garbage Collection, 垃圾收集)</b>, 下面我们分别介绍一下它们.

1><b>MRR</b> 也称为 MRC(Manual Reference Counting, 手动引用计数), 就是由程序员自己负责管理对象生命周期,负责对象的创建和销毁.

2><b>ARC</b>.采用和 MRR 一样的内存引用计数管理方法, 但不同的是, 它在编译时会在何时的位置插入对象内存释放, (如 release, autorelease, 和 retain 等), 程序员不用关心对象释放的问题, 苹果推荐在新项目中使用 ARC, 但在 iOS5之前的系统中不能采用 ARC.

3><b>GC</b>. 在Objective_C2.0之后, 内存管理出现了类似于 Java 和 C#的内存垃圾收集技术, 但是垃圾收集与 ARC 一直运行, 垃圾收集是后台有一个线程负责检查已经不再使用的对象,然后释放之. 由于后台有一个线程一直运行, 一次会严重影响性能, 这也是 Java 和 C#程序的运行速度无法超越 C++的主要原因. GC 技术不能应用于 iOS 开发, 只能应用于Mac OS X 开发.

从上面的介绍可知, iOS 采用 MRR 和 ARC 这两种方式, ARC 是苹果推荐的方式, MRR 方式相对比较原始, 对于程序员的能力要求很高, 但是它很灵活, 方便, 很不容易驾驭好.

<h4>内存泄露问题的解决</h4>
<h5>1>Analyze + Leaks 的使用</h5>
内存泄露指当一个对象或变量在使用完成后没有释放掉, 这个对象一直占用着这部分内存, 直到应用停止. 如果这种对象过多,内存就会耗尽,其他应用就无法运行.这个问题在 C++, C 和 Objective-C的 MRR 中是比较普遍的问题.

从理论上讲, 内存泄露是由对象或变量没有释放引起的, 但实践证明并非所有的未释放的对象或变量都会导致内存泄露, 这与硬件环境和操作系统系统环境有关, 因此我们需要检测工具帮助我们找到这些"泄漏点".

在 Xcode 中, 共提供了两种工具帮助查找泄漏点,
<b> Analyze 和 Instruments. </b>
<b>Analyze 是静态分析工具.</b> 可以通过 Product ->Analyze 菜单项启动. 快捷键: CMD+shift +b.
<b>Instruments:是动态分析工具</b>, 它与 Xcode 集成在一起,可以在 Xcode 中通过 Product ->Profile 菜单项启动. 快捷键 CMD + i.它有很多跟踪模块可以动态分析和跟踪内存, CPU 和文件系统.

Instruments动态分析工具

我们可以结合使用这两个工具查找泄漏点. 先使用 Analyze 静态分析查找可疑泄漏点, 再用Instruments动态分析中的 Leaks 和 Allocations 跟踪模板进行动态跟踪分析, 确认这些点是否泄漏, 或者是否有新的泄漏点出现等.
1>在 Analyze 静态分析结果中, 凡是有图标


分析结果图标

出现的行都是工具发现的疑似泄漏点.

疑似泄漏点所在行

点击疑似泄漏点行末尾的分叉图标,会展开分析结果.
这里使用 Analyze 静态分析查找出来的泄漏点,称之为"可疑泄漏点".之所以称之为"可疑泄漏点",是因为这些点未必一定泄露,确认这些点是否泄露, 还要通过 Instruments 动态分析工具的 Leaks 和 Allocations 跟踪模板. Analyze 静态分析只是一个理论上的预测过程.
在 Xcode 中通过 Product ->Profile 菜单项启动 Instruments 动态分析工具, 接着选择 Leaks 模板, 打开界面如下:

Leaks

在 instruments 中,虽然选择了 Leaks 模板,但默认情况下也会添加 Allocations 模板.基本上凡是内存分析都会使用 Allocations 模板, 它可以监控内存分布情况, 选中 Allocations 模板,(图1区域),右边的3区域会显示随着时间的变化内存使用的折线图,同时在4区域会显示内存使用的详细信息,以及对象分配情况. 点击 Leaks 模板(图中2区域), 可以查看内存泄露情况。如果在3区域有 红X 出现, 则有内存泄露, 4区域则会显示泄露的对象.

点击泄露对象可以在(下图)看到它们的内存地址, 占用字节, 所属框架和响应方法等信息.
打开扩展视图, 可以看到右边的跟踪堆栈信息, 其中
![Uploading Paste_Image_349106.png . . .]
图标所示的条目是我们自己的应用的代码,点击它即可进入程序代码.


Paste_Image.png

<h4>具体使用</h4>
1.Allocations纪录了内存分配,用来优化内存使用的
2.Leaks用来分析内存泄漏。ARC中引起的内存泄漏原因就是引用环。

<b>第一步</b>先选择Leaks和Leaks by Backtrace.这里可以看到那些对象内存泄漏了,泄漏了多少,这个就是简单看看,没有太多调试意义。

Leaks by Backtrace.

<b>第二步</b>然后看看Call Tree,因为Call Tree会给我们大概的位置,有时候会给我们精确的位置,不过要看运气了。
然后,再右面选择Invert Call Tree和Hide System Library


Call Tree

然后双击 上文图片中的任意一行,就会跳到代码处内存泄漏的地方(事实上,到这步,很多内存泄漏的问题都会被发现),当然也有一些泄露还是看不出来的.

<b>第三步</b>然后我们选择对ARC调试很有用的一个部分Circles & Roots,通过这个我们可以看到详细的ARC引用计数过程。
然后,我们看到如下图

小的红色矩形点击可以看到引用计数的详细信息(ARC 就是自动引用计数,计数为0,则对象会被释放)
大的红色矩形可以绘制对象引用环的图,这里如果是我们自己的东西,就能看出来各个对象之间的引用.

Circles & Roots

如果这里没有引用环的图. 首先我们找一下我们自定义的对象,正常完成任务这个对就应该释放的. 为了确认这个对象有没有释放, 可以重写 dealloc 方法, 在此方法中 log 释放信号, 看看是否被释放.
如果这里就是没有释放,我们可以点击这儿对象后的箭头详细的看下, 这个对象的引用计数变化如图.

All 表示所有的引用计数变化
Unpaired表示那些为成对的变化``(成对就是leaks识别出了对应的+1,-1)
By Group会把相关的变化分成一组,
ByTime会按照顺序列出引用计数变化

Paste_Image.png

我们选择Unpaired 和 ByGroup,看到如图

Paste_Image.png

按照顺序看(最左边的标号)
4 这里,引用计数是一,这是正确的,因为到这里正常就是应该是OperationQueue保存一个Operation的引用。 于是,我们把正常的划掉

Paste_Image.png

再继续看,download start 标号6和8是对应的,继续排除问题出现在这里(当然问题不可能出现在这里,这是系统的API,一定会释放,就是简单教大家如何看)

Paste_Image.png

再看看,+1的还剩下标号7 和 11,7 是正常的为Operation分配线程,应当会+1,而11就是我们的问题所在了(大部分Delegate都不会使引用+1)。 我们再看下文档

@property(readonly, retain) id< NSURLSessionDelegate > delegate

原来这个代理是retain啊,不是assign或者weak。所以形成了这样的引用环。

Paste_Image.png

那么怎么办呢?有问题下看文档,我们看到图片中引起引用计数加一的是

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id<NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue:

看下文档,发现了这个地方

Paste_Image.png

于是,我们要手动的去断开强引用,于是,我们手动去断开

-(void)setOperationFinished
{ 
[self.session invalidateAndCancel];
}

再运行下看看,能够正常的Dealloc了.

总结:其实大多数问题在双击上文的代码部分就可以解决了,少数问题需要详细的分析ARC引用过程。

<b>写到最后</b>

如果我们未发现表示内存泄露的红 X, 但是我们想进一步评估某个对象对于内存的应用, 可以看看 Allocations 模板的折线图. 反复执行从创建对象 -> 销毁对象 这个过程, 如果总占用内存数会随之增加, 这说明这个对象没有释放, 有些时候虽然占用的内存不是很严重, 但是也会增加占用内存, 因此必须释放这个对象.

提示:有些情况下, 对象没有释放是无法检测到的,反复测试内存占用也没有明显的增加, 这时最好在配置比较低的设备上测试一下, 如果问题依然, 可以不用释放对象. 但是从编程习惯上讲, 我们应该释放该对象.

事实上,内存泄露是及其复杂的问题, 工具使用是一方面, 经验是另一方面. 提高经验, 然后借助工具才能解决内存泄露的根本.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容