学习笔记:Android Profiler 工具的使用

该篇记录来自,网络的各种综合,感谢这些作者:

   https://www.jianshu.com/p/e75680772375         

   https://blog.csdn.net/niubitianping/article/details/72617864

 开发者官网:

https://developer.android.google.cn/studio/profile/cpu-profiler

https://developer.android.google.cn/studio/profile/memory-profiler

https://developer.android.google.cn/studio/profile/network-profiler

 ——————————————————————————————————

##1. Android Profiler  的介绍

     Android Studio 3.0 采用全新的 **Android Profiler ** 窗口取代 Android Monitor 工具。 这些全新的分析工具能够提供关于应用 CPU、内存和网络 Activity 的实时数据。 您可以执行基于样本的函数跟踪来记录代码执行时间、采集堆转储数据、查看内存分配,以及查看网络传输文件的详情。

  Android Profiler 主要有为三大模块: cpu、内存 、网络。

打开 Android Profiler 窗口的两种方式:

 @@1. 通过android studio 底部面板 ,选择相应的调试设备

  

@@2.通过 ,点击 View > Tool Windows > Android Profiler(也可以点击工具栏中的 Android Profiler )。选择相应的调试设备

当您启动 Android Profiler 后,它会持续收集分析数据,直至您断开设备连接或点击 Close

##2.CPU Profiler概述

打开CPU分析器时,它会立即开始显示应用程序的CPU使用情况和线程活动:

##1.记录和检查函数跟踪

    要开始记录函数跟踪,从下拉菜单中选择 Sampled 或 Instrumented 记录配置,或选择您创建的自定义记录配置,然后点击 Record 。 与应用交互并在完成后点击 Stop recording  。 分析器将自动选择记录的时间范围,并在函数跟踪窗格中显示其跟踪信息,如图 2 所示。如果您想检查另一个线程的函数跟踪,只需从线程 Activity 时间线中选中它。

 

@@1. 使用Call Chart选项卡检查跟踪Call Chart选项卡提供一个方法跟踪的图形表示,其中一个方法调用(或调用者)的周期和时间在水平轴上表示,而它的callees则显示在垂直轴上。对系统api的方法调用以橙色显示,调用您的应用程序自己的方法以绿色显示,方法调用第三方api(包括java语言api)以蓝色显示。下面的图显示了一个示例调用图,并说明了给定方法的自时间、子时间和总时间的概念。

 

提示: 如果想要跳转到方法的源代码,请右键单击该方法,然后选择Jump to Source。这可以从任何窗格选项卡工作。

@@2. 使用火焰图表(Flame Chart)选项卡检查痕迹

Flame Chart 火焰图选项卡提供了一个反向调用图表,聚合了相同的调用堆栈。也就是说,收集相同的调用序列的相同方法被收集并表示为火焰图中的一个较长的栏(而不是将它们显示为多个更短的条,如调用图所示)。这样就更容易看出哪些方法消耗的时间最多。然而,这也意味着横轴不再表示时间轴,相反,它表示每个方法执行的相对时间。

为了帮助说明这个概念,考虑下面图4中的调用图表。注意,方法D对B(B1、B2和B3)进行多次调用,其中一些调用B对C(C1和C3)进行调用。

因为B1、B2和B3共享相同的序列调用者(A→D→B)聚合,如下所示。同样,C1和C3聚合,因为它们共享相同的序列调用者(A→D→B→C)注意不包括C2,因为它有不同的调用者序列(A→D→C)。

聚合方法调用用于创建flame 图,如下图所示。注意,对于任何给定的方法调用,在flame图中,消耗最多CPU时间的callees(被调用者)首先出现。 

@@2. 使用自上而下和自下而上检查

Top Down选项卡显示方法调用的列表,扩展方法节点显示其callees。下图显示了上面的图3中调用图的顶部向下图。图中的每个箭头都是从调用者到callee(被调用者)。

下图所示,在顶部的down选项卡中扩展方法A的节点将显示它的callees、方法B和D。在此之后,扩展方法D的节点将暴露它的callees、方法B和C,等等。与火焰图选项卡类似,顶部向下的树聚合跟踪信息,用于共享相同调用堆栈的相同方法。也就是说,火焰图标签提供了顶部下标签的图形表示。

Top Down选项卡提供以下信息,以帮助描述在每个方法调用上花费的CPU时间(在选定的时间段内,时间也代表线程总时间的百分比):

  • Self:方法调用用于执行自己的代码而不是它的callees的时间量,如上面的图3所示。
  • Children:方法调用花费的时间用于执行其被调用者,而不是其自己的代码,如图3中的方法D所示。
  • Total:方法的Self和Children的时间的总和。这表示应用程序执行方法调用的总时间量,如图3所示的方法D。 

Bottom Up选项卡显示一个方法调用列表,扩展方法的节点显示其调用者。使用上图所示的例子中,下图提供了一个自下而上方法C .在自下而上的树中打开方法C的节点,显示每个独特的调用者,方法B和d .注意,虽然B两次调用C,B当扩大节点只出现一次自下而上方法C的树。再此之后,展开节点B显示其调用者方法A和D.

  

Bottom Up选项卡对于那些消耗最多(或最少)CPU时间的方法的排序方法很有用。您可以检查每个节点,以确定哪些调用者在调用这些方法上花费最多的CPU时间。与上面的树相比,底部树中每个方法的定时信息都是在每棵树的顶部(顶部节点)的方法。在记录期间,CPU时间也被表示为线程总时间的百分比。下表有助于解释如何解释顶级节点及其调用方方法(子节点)的定时信息。

@@3.创建记录配置

您可以从 Android Studio 为您提供的记录配置中选择一个配置,如 Sampled 或 Instrumented,也可以创建自己的记录配置。 要创建或编辑自定义配置,或检查现有默认配置,可通过从记录配置下拉菜单中选择 Edit configurations 来打开 CPU Recording Configurations 对话框。

 

##3.Memory Profiler概述

Memory Profiler ,可帮助您识别导致应用卡顿、冻结甚至崩溃的内存泄漏和流失。 它显示一个应用内存使用量的实时图表,让您可以捕获堆转储、强制执行垃圾回收以及跟踪内存分配。

内存使用量时间线,其包含以下内容:

  • 一个显示每个内存类别使用多少内存的堆叠图表,如左侧的 y 轴以及顶部的彩色键所示。
  • 虚线表示分配的对象数,如右侧的 y 轴所示。
  • 用于表示每个垃圾回收 Event 的图标。

 

@@1.计算内存

@@2.查看内存分配

内存分配显示内存中每个对象是如何分配的。 具体而言,Memory Profiler 可为您显示有关对象分配的以下信息:

  • 分配哪些类型的对象以及它们使用多少空间。
  • 每个分配的堆叠追踪,包括在哪个线程中。
  • 对象在何时被取消分配(仅当使用运行 Android 8.0 或更高版本的设备时)。

如果您的设备运行 Android 8.0 或更高版本,您可以随时按照下述方法查看您的对象分配: 只需点击并按住时间线,并拖动选择您想要查看分配的区域(如视频 1 中所示)。 不需要开始记录会话,因为 Android 8.0 及更高版本附带设备内置分析工具,可持续跟踪您的应用分配。

视频 1. 对于Android 8.0 及更高版本,选择一个现有时间线区域以查看对象分配(https://storage.googleapis.com/androiddevelopers/videos/studio/memory-profiler-allocations-jvmti.mp4

如果您的设备运行 Android 7.1 或更低版本,则在 Memory Profiler 工具栏中点击 Record memory allocations 。 记录时,Android Monitor 将跟踪您的应用中进行的所有分配。 操作完成后,点击 Stop recording (同一个按钮;请参阅视频 2)以查看分配。

视频 2. 对于 Android 7.1 及更低版本,您必须显式记录内存分配(https://storage.googleapis.com/androiddevelopers/videos/studio/memory-profiler-allocations-record.mp4

在选择一个时间线区域后(或当您使用运行 Android 7.1 或更低版本的设备完成记录会话时),已分配对象的列表将显示在时间线下方,按类名称进行分组,并按其堆计数排序。

注:在 Android 7.1 及更低版本上,您最多可以记录 65535 个分配。 如果您的记录会话超出此限值,则记录中仅保存最新的 65535 个分配。 (在 Android 8.0 及更高版本中,则没有实际的限制。)

要检查分配记录,请按以下步骤操作:

  1. 浏览列表以查找堆计数异常大且可能存在泄漏的对象。 为帮助查找已知类,点击 Class Name 列标题以按字母顺序排序。 然后点击一个类名称。 此时在右侧将出现 Instance View 窗格,显示该类的每个实例,如图 3 中所示。
  2. 在 Instance View 窗格中,点击一个实例。 此时下方将出现 Call Stack 标签,显示该实例被分配到何处以及哪个线程中。
  3. 在 Call Stack 标签中,点击任意行以在编辑器中跳转到该代码

图 3. 有关每个已分配对象的详情显示在右侧的 Instance View 中。

默认情况下,左侧的分配列表按类名称排列。 在列表顶部,您可以使用右侧的下拉列表在以下排列方式之间进行切换:

  • Arrange by class:基于类名称对所有分配进行分组。
  • Arrange by package:基于软件包名称对所有分配进行分组。
  • Arrange by callstack:将所有分配分组到其对应的调用堆栈。

@@3.捕获堆转储

堆转储显示在您捕获堆转储时您的应用中哪些对象正在使用内存。 特别是在长时间的用户会话后,堆转储会显示您认为不应再位于内存中却仍在内存中的对象,从而帮助识别内存泄漏。 在捕获堆转储后,您可以查看以下信息:

  • 您的应用已分配哪些类型的对象,以及每个类型分配多少。
  • 每个对象正在使用多少内存。
  • 在代码中的何处仍在引用每个对象。
  • 对象所分配到的调用堆栈。 (目前,如果您在记录分配时捕获堆转储,则只有在 Android 7.1 及更低版本中,堆转储才能使用调用堆栈。)

图 4. 查看堆转储

要捕获堆转储,在 Memory Profiler 工具栏中点击 Dump Java heap  。 在转储堆期间,Java 内存量可能会暂时增加。 这很正常,因为堆转储与您的应用发生在同一进程中,并需要一些内存来收集数据。

堆转储显示在内存时间线下,显示堆中的所有类类型,如图 4 所示。

注:如果您需要更精确地了解转储的创建时间,可以通过调用 dumpHprofData() 在应用代码的关键点创建堆转储。

要检查您的堆,请按以下步骤操作:

  1. 浏览列表以查找堆计数异常大且可能存在泄漏的对象。 为帮助查找已知类,点击 Class Name 列标题以按字母顺序排序。 然后点击一个类名称。 此时在右侧将出现 Instance View 窗格,显示该类的每个实例,如图 5 中所示。
  2. 在 Instance View 窗格中,点击一个实例。此时下方将出现 References,显示该对象的每个引用。

    或者,点击实例名称旁的箭头以查看其所有字段,然后点击一个字段名称查看其所有引用。 如果您要查看某个字段的实例详情,右键点击该字段并选择 Go to Instance

  3. 在 References 标签中,如果您发现某个引用可能在泄漏内存,则右键点击它并选择 Go to Instance。 这将从堆转储中选择对应的实例,显示您自己的实例数据。

默认情况下,堆转储不会向您显示每个已分配对象的堆叠追踪。 要获取堆叠追踪,在点击 Dump Java heap 之前,您必须先开始记录内存分配。 然后,您可以在 Instance View 中选择一个实例,并查看 Call Stack 标签以及 References 标签,如图 5 所示。不过,在您开始记录分配之前,可能已分配一些对象,因此,调用堆栈不能用于这些对象。 包含调用堆栈的实例在图标  上用一个“堆栈”标志表示。 (遗憾的是,由于堆叠追踪需要您执行分配记录,因此,您目前无法在 Android 8.0 上查看堆转储的堆叠追踪。)

在您的堆转储中,请注意由下列任意情况引起的内存泄漏:

  • 长时间引用 ActivityContextViewDrawable 和其他对象,可能会保持对 Activity 或 Context容器的引用。
  • 可以保持 Activity 实例的非静态内部类,如 Runnable
  • 对象保持时间超出所需时间的缓存。

 

在类列表中,您可以查看以下信息:

  • Heap Count:堆中的实例数。
  • Shallow Size:此堆中所有实例的总大小(以字节为单位)。
  • Retained Size:为此类的所有实例而保留的内存总大小(以字节为单位)。

在类列表顶部,您可以使用左侧下拉列表在以下堆转储之间进行切换:

  • Default heap:系统未指定堆时。
  • App heap:您的应用在其中分配内存的主堆。
  • Image heap:系统启动映像,包含启动期间预加载的类。 此处的分配保证绝不会移动或消失。
  • Zygote heap:写时复制堆,其中的应用进程是从 Android 系统中派生的。

默认情况下,此堆中的对象列表按类名称排列。 您可以使用其他下拉列表在以下排列方式之间进行切换:

  • Arrange by class:基于类名称对所有分配进行分组。
  • Arrange by package:基于软件包名称对所有分配进行分组。
  • Arrange by callstack:将所有分配分组到其对应的调用堆栈。 此选项仅在记录分配期间捕获堆转储时才有效。 即使如此,堆中的对象也很可能是在您开始记录之前分配的,因此这些分配会首先显示,且只按类名称列出。

默认情况下,此列表按 Retained Size 列排序。 您可以点击任意列标题以更改列表的排序方式。

在 Instance View 中,每个实例都包含以下信息:

  • Depth:从任意 GC 根到所选实例的最短 hop 数。
  • Shallow Size:此实例的大小。
  • Retained Size:此实例支配的内存大小(根据 dominator 树)。

 

在捕获堆转储后,仅当分析器运行时才能在 Memory Profiler 中查看数据。 当您退出分析会话时,您将丢失堆转储。 因此,如果您要保存堆转储以供日后查看,可通过点击时间线下方工具栏中的 Export heap dump as HPROF file,将堆转储导出到一个 HPROF 文件中。 在显示的对话框中,确保使用 .hprof 后缀保存文件。

然后,通过将此文件拖到一个空的编辑器窗口(或将其拖到文件标签栏中),您可以在 Android Studio 中重新打开该文件。

要使用其他 HPROF 分析器(如 jhat),您需要将 HPROF 文件从 Android 格式转换为 Java SE HPROF 格式。 您可以使用 android_sdk/platform-tools/ 目录中提供的 hprof-conv 工具执行此操作。 运行包括以下两个参数的 hprof-conv 命令:原始 HPROF 文件和转换后 HPROF 文件的写入位置。 例如:

hprof-conv heap-original.hprof heap-converted.hprof

 

@@4. 具体分析一下如何使用Memory Profiler查找内存泄漏.(https://www.jianshu.com/p/e75680772375 多谢作者)

查找内存泄漏有以下几个方式
1、一般我排查内存泄漏的方式是,启动应用,看一下当前内存使用了多少,使用应用一段时间后(当然你不想亲自动手点来点去,也可以使用monkey进行一次自动化测试), 退回到应用首页,看看当前内存又是多少。进行一次heap dump, 看看结果,分析一下有没有可疑的对象分配(比如说大量重复的Activity,同一个类型对象比较多,对象内存占用较大)


2、发现可疑点后,通过分析结果,可以找到相应代码,找到代码当然也能找到使用代码的场景,例如是Activity泄漏,反复进行画面的跳转(如果你的应用支持横竖平切换的话,也可以反复旋转屏幕),然后强制gc回收,看看内存是否存在只增不减的情况.


3、也可以使用allocation跟踪一段时间内存分配情况,拿出来做分析
4、最后推荐一款leakcanary工具使用(具体可看:https://github.com/square/leakcanary

下面开始正式的栗子:
我启动了一个疑似存在内存泄漏app,然后使用了一段时间,进行了一次heap dump, 结果如下

很明显我发现了一个可疑的类OutOfMemActivity, 它存在多个实例,实际上在已知该app业务逻辑中是不应该会有这么多OutOfMemActivity实例的,于是我变点开它的Instance View.
可疑点如红色剪头所指,因为外部类实例引用到Activity都是不正常的操作,这里Broadcast的实例引用到了Activity.

点击跳转到源码,发现是内部类引用到外部类实例(Activity)的情况导致了内存泄漏.

 

##3. 网络分析器(Network Profiler)

Network Profiler 能够在时间线上显示实时网络 Activity,包括发送和接收的数据以及当前的连接数。 这便于您查看应用传输数据的方式和时间,并据此对底层代码进行适当优化。

 

 

 

 

 

 

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

荣•厚德载物

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值