iOS 内存分析
iOS 内存分析
最近在做关于APP 内存方面的分析,去尽量优化iOS 侧 APP 的内存。原本使用的是之前自己掌握的方式,比如 Memory leaks , Memory Allocations
每一项工具都有针对性的内容,在进一步优化的时候发现了原来可以使用终端方式来查询问题。一个对于自己全新的领域。
引述一下关键字:iOS Memory Deep Dive WWDC2018
WWDC2018 , 2018年 。大概如果是苹果开发铁杆粉都已经悉数掌握。但是很多开发者似乎对这块儿知识都了解较少,如何具体使用也不一定都能掌握。我这儿整理一下对自己查找问题中的一些相关性,也顺带做一下总结,提醒一下自己。
前言
利用自己在实际开发中遇到的相关问题来具体讲解如何在iOS中做内存分析,怎样去针对性优化。
怎样去观察内存占用
需要卸载掉哪些内存
怎样观察内存
大家都在Xcode 下经常开发,Xcode Memory gauge 这个界面大家应该都不会陌生
在当前界面,能够提供数字,百分比,内存使用危险程度的通用观察界面。针对于平常查看内存占用大小比较方便,但是对于内存问题,这块儿能提供的内容相当有限。但是能够提示开发者内存占用的波动,从而引起关注。
iOS 内存介绍
iOS Memory Deep Dive 讲了关于iOS 在内存方面的使用和统计方式。提到了在iOS 操作系统中,内存的统计方式是按照分页的方式。内存又会被细分为 物理内存 和虚拟内存。 APP 的运行是一定要基于内存之上的,物理内存和虚拟内存的主要作用如下。
物理内存:设备运行时为操作系统和各种程序提供临时储存空间
虚拟内存:为每一个进程提供了一个一致的、私有的地址空间;其主要作用是:保护了每个进程的地址空间不会被其他进程破坏,降低内存管理的复杂性。 虚拟内存是进程运行时所有内存空间的总和,并且可能有一部分不在物理内存中。
iOS系统是按页分配内存的,每个page通常是16KB
1 | Memory in use = Number of pages * Page size |
iOS内存可以分为clean memory和dirty memory。当用户(也就是程序员)申请分配内存时,系统只会对这块内存进行标记,这时只会分配虚拟内存,而不会分配物理内存,此时内存是clean memory。当对这块内存进行数据填充时,才会分配物理内存,内存变为dirty memory。
1 | Memory Footprint = Dirty Memory + Compressed Memory |
针对内存问题,我们考虑的重点也是去减少 Dirty Memory
具体查找步骤
根据已知的信息,尝试去实践一下如何查找内存消耗,这次使用命令行方式。
以第一张图 27.8M 为例。首先修改 iOS Scheme , 勾选 Malloc Stack Logging
并选中为 Live Aloocations Only
然后就是运行中等待时机到来,点击Debug Memory Graph
得到内存图。可以通过 File --> Export Memory Graph
到处文件到指定位置。
1 | #终端执行下面代码 |
从我们已知的信息可以知道 , Dirty Memory 是我们关注的重点。于是发现了 REGION TYPE 是 MALLOC_LARGE
1 | $ vmmap -verbose memory.memgraph | grep "MALLOC_LARGE" #获取详细的关于内存分配的 在归属于 “MALLOC_LARGE” 这里的内容 |
从图中我们可以容易的发现,内存地址为 0x1146e4000 。 在这样的情况下,我们可以借助于另外一个命令 malloc_history
1 | $ malloc_history memory.memgraph -fullStacks 0x1146e4000 # 获取地址块儿的堆栈信息 |
根据我们查到的调用堆栈,我们发现是因为 new 操作,导致了内存分配,源头应该在于 InstanceDemo 这个类的构造函数。
贴上源码,是这里引起的内存分配无疑。我们同时也发现,Dirty memory 也是 9.8M. 如果我们不给数组赋值呢?
我们注释掉数组赋值,重新走一遍儿上面的流程。
于是发现了,同样 MALLOC_LARGE
中的 VIRTUAL SIZE 是 10M , 但是DIRTY SIZE 只剩下了 208K
如果我们细跟入进去会发现
是同样能够查到内存分配的位置。但是因为只有内存申请,没有使用,分配的区域被放在了虚拟内存,所以Dirty MEMARY 并没有相应标记。
在查询内存问题的时候还有另外一个命令可以使用,就是
1 | $ leaks -traceTree 0x1118cc000 memory_new.memgraph |
通过这个命令可以知道 m_instance 被持有引用,可能会出现内存泄漏。
Demo 依旧会提供,主要对内存如何分析和查找可能性提出一些方法。 我们同时还可以通过Xcode 提供的 VM Tracker 等工具用来具体指向我们怀疑的点。一般来讲,图片资源占用的内存会比较大,如果作为优化的方向,首选见效处理就是规范化图片资源。