【iOS开发】---- 使用Instrument检查内存占用过多的代码

      本文要介绍的是如何使用Instrument来检查代码中哪里占用内存较多。

      先上一篇《Instrument使用指南》(点击这里去下载)中的文章,然后再用例子来说明如何使用。

      当然,你可以跳过分割线的内容,不过建议阅读以下。



-----------------------------------------我是万恶的分割线----------------------------------------------

5.2.2 使用Allocations Instrument工具分析数据

    Allocations instrument 工具是一个跟踪所有由应用程序分配的内存的工具。所以你可以使用那些信息来识别在你应用程序里面的内存分配模式,并识别你的应用程序内存效率低下的地方。Allocations instrument 提供了和之前应用程序的ObjectAlloc 一样甚至更好的数据修整和修剪设施。因为这整合在 Instruments 应用环境里面,你也可以使用该 instrument 工具来关联你应用程序的内存行为到其他类型的行为。

    因为它跟踪整个应用程序生命周期的内存分配,你必须从 Instruments 应用里面加载你的程序以便 Allocations instrument 工具可以收集它所需要的数据。在加载的时候,Allocations instrument 使用系统中已有的挂钩(hooks)来记录与你应用程序中分配和释放事件相关的信息,无论这些事件起源于系统标准分配入口还是你自己自定义的分配库。随着数据流的到来,instrument 更新并实时的向你显示内存是如何被分配的。

    Allocations instrument 可以工作在使用标准分配函数(如 malloc,calloc 或free)的应用程序,而且也也可以工作在使用垃圾回收(garbage collected)的应用程序上面。后一种情况,收集器依然调用 free 来释放 GC-aware(GC 感知)内存。Allocations instrument 同样可以在构建在分配内存之上的例程里面工作,包括 CoreFoundation 和 Cocoa 的内存分配例程。

注意:Allocations instrument 替代了 ObjectAlloc 应用程序,而 ObjectAlloc 应用程序在 Mac OSX v10.5 及其之后不可用。


分析对象分配的数据
    Allocation instrument 工具的目的是为你显示你的应用程序如何使用内存。内

    存是系统重要的资源,你应该明智的使用它。每个内存分配都包含了直接成本和潜在的长期成本。直接成本就是它分配内存所消耗的时间,包括创建新的虚拟内存页面和把它们映射到物理内存上面。它也有可能包括把陈旧的内存页面写入硬盘。而从长远来看,保持块状的物理内存可能触发系统额外的页面,这和其他页面操作一样可能对系统性能损耗很大。

    和所有工具一样,Allocation 工具开始的地方也是跟踪面板。默认配置下,跟踪面板图形化你当前应用程序使用内存数量的净额。使用 instrument 的检查器,你可以修改视图让它显示分配的密度,即内存分配发生的地方,或你也可以让它显示堆栈的深度。分配密度图可以让你查看在你程序里面内存分配发生的频率。分配密度的尖峰意味着潜在的瓶颈,而你可以通过预先分配块或减少对其他块的依赖来减缓该情况。

    无论你使用检查器的任何显示选项,跟踪面板默认情况下都会显示所有类型对象的分配情况。为了集中于特定内存分配的子集,你可以使用详细面板来配置你想要在跟踪面板图形显示的对象。为了集中于特定的对象类型或块大小,打开详细面板并把它设置为列表模式(table mode)。在该模式下,详细面板通过对象类型和大小对内存分配进行排序。图形的列包含了复选框可以让你想要选择图形化的对象。取消所有Allocations 的复选框(默认情况下就是这样),然后选择其他对象类型的复选框来相应更新跟踪面板。如果你勾选了多个复选框,Allocations instrument 会为图形生成不同颜色的层。

   详细面板(列表模式下)显示其他有用的信息来帮你发现潜在的分配问题。列表中整体分配的净分配的列显示了当前活动对象和它有史以来创建数量的直方图。随着净分配占整体分配比例缩小,直方图的条形颜色会跟着改变。蓝色的直方图条形代表了合理的比例,而当改变为红色时意味着比例降低,可能需要核查一下。

   尽管列表模式对于你获得内存分配的全局图非常有帮助,但是详细面板集合了三个视图模式的优点。表 5-3 描述了每个模式的显示信息和你如何使用这些模式来发现问题。 



     Allocations instrument 的扩展详细面板主要显示了所选择的分配事件的堆栈信息。对于某些分配事件,该面板也显示了关于事件的描述,包括事件的类型和大小,和对象的引用数(retain count)。该信息可以帮你在你的代码中定位事件。

page57image936

跟踪引用数的事件
    当你把 Allocations instrument 添加到你的文档里面的时候,它的初始化配置

是只记录内存的分配和释放的事件。默认情况下,它不会记录引用数的事件,比如CFRetain 和 CFRelease 的调用。原因是记录引用数的事件会给从进程里面收集数据增加了额外的开销,而且在大部情况是不需要的。然而如果你的代码发生内存泄露,你可能想要配置 Allocations instrument 来记录这些事件作为你努力追查泄露的一部分。特别是,你可以查看任何不匹配的 retain 和 release 的事件来查看一个对象是否最后引用被删除了而它仍然保留着。

    注意:随着“Record referenc counts”选项被设置,Allocations instrument 在模板文档里面查找内存泄露地方,这会帮助你追踪到内存的泄露。

    过滤详细面板的内容
    表 5-4 列出了高级的配置选项,你可以应用它们到 Allocations instrument 记录的事件上面。你使用这些选项来集中于分析特定时间发生的事件,或涉及你代码的特定部分。所有的这些选项仅当使用大纲或图形模式查看数据的时候才可用。在列表模式下,Allocations instrument 显示所有分配的历史记录。 


    当你应用一个 instrument 的配置选项的时候,不要忘记你也可以限制样本数据基于这些样本何时被收集。每个跟踪文档里面的 Inspection Range 控件可以让你查看特定样本点的数据。该特性和其他 instrument 的配置选项组合使用。关于更多如何使用 Inspection Range 控件的信息,参阅“查看一个时间范围的数据”部分。 

-----------------------------------------我是万恶的分割线----------------------------------------------





现在来看看具体如何使用把。

首先我在代码中添加以下代码,让内存不停的消耗:

-(TMQuiltViewCell *)quiltView:(TMQuiltView *)quiltView cellAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *identifierStr = @"photoIdentifier";
    TMPhotoQuiltViewCell *cell = (TMPhotoQuiltViewCell *)[quiltView dequeueReusableCellWithReuseIdentifier:identifierStr];
    if (!cell)
    {
        cell = [[[TMPhotoQuiltViewCell alloc] initWithReuseIdentifier:identifierStr] autorelease];
    }
    for (int i = 1; i<100; i++)
    {
        UIView *view = [[UIView alloc] init];
    }

    cell.photoView.image = [self imageAtIndexPath:indexPath];
    cell.titleLabel.text = [NSString stringWithFormat:@"%d", indexPath.row + 1];
    return cell;
}


上面的for循环中会不停的初始化一个view,这样就会不停的消耗内存。当然,实际中你并不知道哪儿会消耗内存。现在我们要做的就是用工具将这个代码给找出来。

首先点击如下图所示选项:


点击profile。出现如下界面,选Allocations instrument ,如下图所示。


选择了之后,就会出现instrument的面板,具体每个地方做什么用我就不解释了,《instrument使用指南》已经写的很清楚了。

然后要做的就是使内存不停的消耗,因为我这里把代码写在表的代理中,只要不停的滚动表就行了。

不停地一边滚动表格一边观察instrument面板如下图所示位置的变化:


      直方图中,每个柱条(忘了该怎么称呼了,就这么叫吧)里有两种颜色,短的那个表示叫净分配字节数(Net Bytes),是当前已经分配内存但是仍然没有被释放的字节的总数,而长的叫做总分配数(#Overall),是所有当前已经分配内存,包括已经被释放了的对象或内存块的总数。不停的滚动表,会发现一些柱条中短的猛的增加,将他们勾选,然后重点观察。


      过了一会儿,出现如下图所示情况(不一定每次都变得红彤彤的,但是猛地增加应该就有问题了):


可以看到详细面板中有三条大红杠,根据指南中加粗的文字来看它们应该就是问题所在了,将粗箭头所指的游标选中波峰位置,点击细箭头所指位置,跳转到如下界面:


从上图可以看到,绿色箭头所指的一行是灰色的,表示选中的波峰时执行情况,右侧面板粉红箭头指示的地方即耗内存比较多的地方,也许你的右侧面板没出现,点击红色箭头所指示的位置即可。

然后双击右侧粉红箭头所指代码(有两行,先点击第一行),如下图所示:


终于找到了吃内存的地方了!刚才我们只点击了第一行,再点击第二行,你会发现其实与上图中消耗1.3%的地方是一个地方,所以我想只要点击最上面的代码即可,然后一次查看上图中所有消耗内存的代码。


例子用的是瀑布流,如果需要的可以去这里下载:瀑布流下载

以上这些都是我自己总结出来的,也许不对的地方,如果发现不对的地方请指出,谢谢。


  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值