Android 性能优化(五)Heap Dump 的使用

Android Profiler

在新版的 Android studio 中, Profiler 的界面发生了变化,如下图所示。

其中:

  • System Trace:显示整个系统的活动和资源使用情况。比如:应用和系统进程在设备核心和线程中的分布情况;界面渲染的流畅程度;设备和应用级别的耗电量
  • Heap Dump:用于收集和分析堆转储,一般使用这个来分析内存
  • Callstacks Sample:对调用堆栈进行抽样,可以在这里找到调用时间比较长的代码段
  • Java/Kotlin Allocations:记录 Java/Kotlin 分配。比如:分配了哪些类型的对象以及它们使用多少空间;每个分配的堆栈轨迹,包括在哪个线程中。
  • Java/Kotlin Method Recording:记录应用代码执行期间调用的 Java/Kotlin 方法,可让我们查看特定时间点的调用堆栈和 CPU 使用情况(已过滤为仅显示 Java/Kotlin 方法)。此数据有助于识别执行时间长或消耗大量系统资源的代码段。
  • Native Allocations:原生代码表示的对象的分配和解除分配情况
  • View Live Telemetry: 用于实时检查应用,可以大致了解设备的 CPU 使用情况、线程活动和内存使用情况。

这篇文章将介绍新版 Profiler 中,Heap Dump 的使用

Heap Dump

启动 Heap Dump 分析后,可以捕获当前的内存中所有对象的快照,如下图所示:

注意:在转储堆期间,Java 内存量可能会临时性增加。这是因为堆转储需要一些内存来收集数据。

下拉菜单

Heap Dump 界面的第一行有三个下拉菜单,其作用分别是:过滤特定的堆内存分配排列方式指定 Class

过滤特定的堆

如下图所示:

  • View all heaps:查看所有堆
  • View app heap(默认):查看 App 在其中分配内存的主堆
  • View image heap:系统启动映像,包含启动期间预加载的类,此处的分配确保绝不会移动或消失
  • View zygote heap:写时复制堆,其中的应用进程是从 Android 系统中派生的

内存分配排列方式

如下图所示:

  • Arrange by class(默认):默认根据类名对所有分配进行分组
  • Arrange by package:根据软件包名对所有分配进行分组

过滤 Class

如下图所示:

  • Show all classes(默认):显示所有类,包括库中的类 和依赖项
  • Show activity/fragment Leaks:展示泄露的 Activity/Fragment
  • Show project class:仅显示项目定义的类

类列表

设置好第一行的下拉菜单后,我们就可以在类列表中查看对应的内存使用情况。这里以 过滤 Class 设置为 Show project class 为例,如下图所示:

可以看到其中:

  • Classes:指类的种类
  • Leaks:展示泄露数量,双击会自动选中 Show activity/fragment Leaks
  • Count:堆中对象的分配数量
  • Native Size:此对象类型使用的原生内存总量(单位字节)
  • Shallow Size:指的是对象实例自身占用的内存大小,不包括它引用的其他对象的内存。(单位字节)
  • Retained Size :是该对象及其独占引用的其他对象(基于支配树 dominator tree)的总内存大小(单位字节)

注意:Native Size 只有在使用 Android 7.0 及更高版本时,才会看到此列,会在此处看到采用 Java 分配的某些对象的内存,因为 Android 对某些框架类(如 Bitmap)使用原生内存

假设对象的依赖关系如下图所示,此时

css 复制代码
Shallow Size = size(A)

// 由于对象 B 只被对象A引用,如果对象A被回收,那么对象B也会被回收
Retained Size = size(A) + size(B)

如果 B 对象被其他对象引用,则此时

txt 复制代码
Shallow Size = size(A)

// 由于对象 B 同时被对象A和对象C引用,如果对象A被回收,那么对象C不会被回收
Retained Size = size(A)

更多关于 Shallow Size & Retained Size 具体可以看 Android优化篇|Shallow Size & Retained Size

上图所示,是具体的类所占用的内存。其中 Allocations 是指堆中的对象的分配数,和 Count 是相同的。

注意,Retained Size 一定是大于或者等于 Shallow Size 的。在 heap dump 的界面中,有时候会出现 Retained Size 小于 Shallow Size 的情况,这可能是 Android studio 的bug,具体可以看 issuetracker.google.com/issues/2820...

内存泄漏

点击 Leaks 或者选择 Show activity/fragment Leaks 可以展示内存泄漏界面,如下图所示:

如下图所示,对于 LeakActivity 对象,其中 Depth 是指从任意 GC 根到选定实例的最短跳数。

点击泄漏的 LeakActivity 对象,可以看到该对象的实例详情,如下所示。

其中:

  • Fields:显示此实例中的所有字段。
  • References:显示对 Instance 标签页中突出显示的对象的每个引用。

对于内存泄漏的排查,一般我们需要选中 Show nearest GC root only,显示最近的 GC root。通过这个来排查哪里还在引用该 Activity 或者 Fragment。

注意:在以下情况中可能会产生误报的问题:

  • 已创建 Fragment,但尚未使用它。
  • 正在缓存 Fragment,但它不是 FragmentTransaction 的一部分

由于在此界面,无法直接强制触发 GC,我们需要通过以下方式来实现类似的效果:

  • 将设备从竖屏旋转为横屏,然后反复旋转多次 在不同 activity 状态下使用。
  • 当处于不同的 activity 状态时,在我们的应用与其他应用之间切换。 例如,导航到主屏幕,然后返回我们的应用。

参考

相关推荐
冰_河7 小时前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化
阿巴斯甜18 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker18 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952719 小时前
Andorid Google 登录接入文档
android
黄林晴21 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android