Android Studio 3.0 采用全新的
Android Profiler
窗口取代
Android Monitor
工具。 这些全新的分析工具能够提供关于应用
CPU
、
内存
和
网络活动
的实时数据。
您可以执行基于样本的函数跟踪来记录代码执行时间、采集堆转储数据、查看内存分配,以及查看网络传输文件的详情。
Android Profiler 的使用方法
Android Profiler 的打开步骤
要打开 Android Profiler 窗口,请按以下步骤操作:
Android Profiler 共享时间线的视图显示如下图所示: Android Profiler 目前可显示共享时间线视图,可以在按钮①的位置选择设备,通过按钮②的位置选择想要的app进程,工具最底部显示了一个时间轴,其中包含了CPU、内存和网络使用的实时图。该窗口还包括时间轴缩放控制按钮③,一个跳转到实时更新的按钮④,以及显示活动状态、用户输入事件和屏幕旋转事件⑤的事件时间轴。
当您启动 Android Profiler 后,它会持续收集分析数据,直至您断开设备连接或点击 Close 。
此共享时间线视图只显示时间线图表。 要使用详细分析工具,请点击与您想查看的性能数据对应的图表。 例如,要使用工具查看堆数据和跟踪内存分配,可点击 MEMORY 图表。
但并不是所有分析数据均默认可见。 如果您看到一条消息,显示“Advanced profiling is unavailable for the selected process”,则需在运行配置中 启用高级分析 。
启用高级分析
要显示高级分析数据,Android Studio 必须在您编译后的应用中插入监控逻辑。高级分析工具提供的功能包括:
要启用高级分析,请按以下步骤操作:
现在重新构建并运行您的应用,即可获取完整的分析功能。但请注意,高级分析会减缓您的构建速度,所以仅当您想要开始分析应用时才启用此功能。
注:对于原生代码,不可使用高级分析功能。 如果您的应用是纯原生应用(不含 Java
Activity
类),则不可使用高级分析功能。 如果您的应用使用了 JNI,则可使用部分高级分析功能,例如 Event 时间线、GC Event、Java 分配对象和基于 Java 的网络活动,但不能检测基于原生的分配和网络活动。
使用 CPU Profiler 检查 CPU 活动 和函数跟踪
使用 CPU Profiler 检查 CPU 活动 和函数跟踪 CPU Profiler 可帮助您实时检查应用的 CPU 使用率和线程活动,并记录函数跟踪,以便您可以优化和调试您的应用代码。点击 Android Profiler 窗口中的 CPU 时间线中的任意位置即可打开 CPU Profiler 。
为什么要分析 CPU 使用率
最大限度减少应用的 CPU 使用率具有许多优势,如提供更快更顺畅的用户体验,以及延长设备电池续航时间。 它还可帮助应用在各种新旧设备上保持良好性能。 与应用交互时,您可以使用 CPU Profiler 监控 CPU 使用率和线程活动。 不过,如需了解应用如何执行其代码的详细信息,您应 记录和检查函数跟踪 。
对于应用进程中的每个线程,您可以查看一段时间内执行了哪些函数,以及在其执行期间每个函数消耗的 CPU 资源。 您还可以使用函数跟踪来识别调用方和被调用方。 调用方指调用其他函数的函数,而被调用方是指被其他函数调用的函数。 您可以使用此信息确定哪些函数负责调用常常会消耗大量特定资源的任务,并尝试优化应用代码以避免不必要的工作。
如果您想收集可帮助您检查原生系统进程的详细系统级数据,并解决掉帧引起的界面卡顿,您应使用 systrace 。
或者,如果您想导出您使用
Debug
类捕获的
.trace
文件,您应使用
Traceview
。
CPU Profiler 概览
当您打开 CPU Profiler 时,它将立即开始显示应用的 CPU 使用率和线程活动。CPU Profiler 的默认视图如下图所示:
如图所示,CPU Profiler 的默认视图包括以下内容:
注: 分析器还会报告 Android Studio 和 Android 平台添加到您的应用进程(如 JDWP、Profile Saver、Studio:VMStats、Studio:Perfa 以及 Studio:Heartbeat,尽管它们在线程活动时间线中显示的确切名称可能有所不同)的线程 CPU 使用率。 这表示 CPU 时间线中应用的 CPU 使用率还可反映这些线程使用的 CPU 时间。 您可以在线程活动时间线中查看其中的一些线程并监控其活动。 (不过,由于分析器线程执行原生代码,因此,您无法为它们记录函数跟踪数据。)Android Studio 将报告此数据,以便当线程活动及 CPU 使用率实际上是由应用代码引发时,您可以轻松识别。
记录和检查函数跟踪
要开始记录函数跟踪,从下拉菜单中选择 Sampled 或 Instrumented 记录配置,或选择您创建的 自定义记录配置 ,然后点击 Record 。 与应用交互并在完成后点击 Stop recording 。 分析器将自动选择记录的时间范围,并在函数跟踪窗格中显示其跟踪信息。如果您想检查另一个线程的函数跟踪,只需从线程活动时间线中选中它。 记录函数跟踪后的 CPU Profiler 视图,如下图所示: 如图所示,记录函数跟踪后的 CPU Profiler 视图包括以下内容:
使用 Memory Profiler 查看 Java 堆和内存分配
Memory Profiler 是 Android Profiler 中的一个组件,可帮助您识别导致应用卡顿、冻结甚至崩溃的内存泄漏和流失。 它显示一个应用内存使用量的实时图表,让您可以捕获堆转储、强制执行垃圾回收以及跟踪内存分配。点击 Android Profiler 窗口中的 MEMORY 时间线中的任意位置即可打开 Memory Profiler 。或者,您可以在命令行中使用 dumpsys 检查您的应用内存,同时 查看 logcat 中的 GC Event 。
为什么应分析您的应用内存
Android 提供一个 托管内存环境 —当它确定您的应用不再使用某些对象时,垃圾回收器会将未使用的内存释放回堆中。 虽然 Android 查找未使用内存的方式在不断改进,但对于所有 Android 版本,系统都必须在某个时间点短暂地暂停您的代码。 大多数情况下,这些暂停难以察觉。 不过,如果您的应用分配内存的速度比系统回收内存的速度快,则当收集器释放足够的内存以满足您的分配需要时,您的应用可能会延迟。 此延迟可能会导致您的应用跳帧,并使系统明显变慢。
尽管您的应用不会表现出变慢,但如果存在内存泄漏,则即使应用在后台运行也会保留该内存。 此行为会强制执行不必要的垃圾回收 Event,因而拖慢系统的内存性能。 最后,系统被迫终止您的应用进程以回收内存。 然后,当用户返回您的应用时,它必须完全重启。
为帮助防止这些问题,您应使用 Memory Profiler 执行以下操作:
如需了解可减少应用内存使用的编程做法,请阅读 管理您的应用内存 。
Memory Profiler 概览
当您首次打开 Memory Profiler 时,您将看到一条表示应用内存使用量的详细时间线,并可访问用于强制执行垃圾回收、捕捉堆转储和记录内存分配的各种工具。Memory Profiler 的默认视图如下图所示:
如图所示,Memory Profiler 的默认视图包括以下各项:
不过,如果您使用的是运行 Android 7.1 或更低版本的设备,则默认情况下,并不是所有分析数据均可见。 如果您看到一条消息,其显示“Advanced profiling is unavailable for the selected process”,则需要 启用高级分析 以查看下列内容:
在 Android 8.0 及更高版本上,始终为可调试应用启用高级分析。
如何计算内存
您在 Memory Profiler 顶部看到的数字取决于您的应用根据 Android 系统机制所提交的所有私有内存页面数。 此计数不包含与系统或其他应用共享的页面。 Memory Profiler 顶部的内存计数图例,如下图所示:
内存计数中的类别如下所示:
即使您的应用中不使用 C++,您也可能会看到此处使用的一些原生内存,因为 Android 框架使用原生内存代表您处理各种任务,如处理图像资源和其他图形时,即使您编写的代码采用 Java 或 Kotlin 语言。
当连接至运行 Android 7.1 及更低版本的设备时,此分配仅在 Memory Profiler 连接至您运行的应用时才开始计数。 因此,您开始分析之前分配的任何对象都不会被计入。 不过,Android 8.0 附带一个设备内置分析工具,该工具可记录所有分配,因此,在 Android 8.0 及更高版本上,此数字始终表示您的应用中待处理的 Java 对象总数。
与以前的 Android Monitor 工具中的内存计数相比,新的 Memory Profiler 以不同的方式记录您的内存,因此,您的内存使用量现在看上去可能会更高些。 Memory Profiler 监控的类别更多,这会增加总的内存使用量,但如果您仅关心 Java 堆内存,则“Java”项的数字应与以前工具中的数值相似。
然而,Java 数字可能与您在 Android Monitor 中看到的数字并非完全相同,这是因为应用的 Java 堆是从 Zygote 启动的,而新数字则计入了为它分配的所有物理内存页面。 因此,它可以准确反映您的应用实际使用了多少物理内存。
注:目前,Memory Profiler 还会显示应用中的一些误报的原生内存使用量,而这些内存实际上是分析工具使用的。 对于大约 100000 个对象,最多会使报告的内存使用量增加 10MB。 在这些工具的未来版本中,这些数字将从您的数据中过滤掉。
查看内存分配
内存分配显示内存中每个对象是如何分配的。 具体而言,Memory Profiler 可为您显示有关对象分配的以下信息:
如果您的设备运行 Android 8.0 或更高版本,您可以随时按照下述方法查看您的对象分配: 只需点击并按住时间线,并拖动选择您想要查看分配的区域。 不需要开始记录会话,因为 Android 8.0 及更高版本附带设备内置分析工具,可持续跟踪您的应用分配。如下如所示:
如果您的设备运行 Android 7.1 或更低版本,则在 Memory Profiler 工具栏中点击 Record memory allocations 。 记录时,Android Monitor 将跟踪您的应用中进行的所有分配。 操作完成后,点击 Stop recording (同一个按钮)以查看分配。如下如所示:
在选择一个时间线区域后(或当您使用运行 Android 7.1 或更低版本的设备完成记录会话时),已分配对象的列表将显示在时间线下方,按类名称进行分组,并按其堆计数排序。
注:在 Android 7.1 及更低版本上,您最多可以记录 65535 个分配。 如果您的记录会话超出此限值,则记录中仅保存最新的 65535 个分配。 (在 Android 8.0 及更高版本中,则没有实际的限制。)
要检查分配记录,请按以下步骤操作:
默认情况下,左侧的分配列表按类名称排列。在列表顶部,您可以使用右侧的下拉列表在以下排列方式之间进行切换:
捕获堆转储
堆转储显示在您捕获堆转储时您的应用中哪些对象正在使用内存。 特别是在长时间的用户会话后,堆转储会显示您认为不应再位于内存中却仍在内存中的对象,从而帮助识别内存泄漏。 在捕获堆转储后,您可以查看以下信息:
要捕获堆转储,在 Memory Profiler 工具栏中点击 Dump Java heap 。 在转储堆期间,Java 内存量可能会暂时增加。 这很正常,因为堆转储与您的应用发生在同一进程中,并需要一些内存来收集数据。
堆转储显示在内存时间线下,显示堆中的所有类类型,如下图所示:
注:如果您需要更精确地了解转储的创建时间,可以通过调用 dumpHprofData() 在应用代码的关键点创建堆转储。
要检查您的堆,请按以下步骤操作:
默认情况下,堆转储不会向您显示每个已分配对象的堆叠追踪。 要获取堆叠追踪,在点击 Dump Java heap 之前,您必须先开始记录内存分配。然后,您可以在 Instance View 中选择一个实例,并查看 Call Stack 标签以及 References 标签,如下图所示。不过,在您开始记录分配之前,可能已分配一些对象,因此,调用堆栈不能用于这些对象。包含调用堆栈的实例在图标 上用一个“堆栈”标志表示。(遗憾的是,由于堆叠追踪需要您执行分配记录,因此,您目前无法在 Android 8.0 上查看堆转储的堆叠追踪。)
默认情况下,堆转储不会向您显示每个已分配对象的堆叠追踪。 要获取堆叠追踪,在点击 Dump Java heap 之前,您必须先开始记录内存分配。然后,您可以在 Instance View 中选择一个实例,并查看 Call Stack 标签以及 References 标签,如下图所示。不过,在您开始记录分配之前,可能已分配一些对象,因此,调用堆栈不能用于这些对象。包含调用堆栈的实例在图标 上用一个“堆栈”标志表示。(遗憾的是,由于堆叠追踪需要您执行分配记录,因此,您目前无法在 Android 8.0 上查看堆转储的堆叠追踪。)
在您的堆转储中,请注意由下列任意情况引起的内存泄漏:
捕获堆转储需要的持续时间标示在时间线中,如下图所示:
在类列表中,您可以查看以下信息:
在类列表顶部,您可以使用左侧下拉列表在以下堆转储之间进行切换:
默认情况下,此堆中的对象列表按类名称排列。 您可以使用其他下拉列表在以下排列方式之间进行切换:
默认情况下,此列表按 Retained Size 列排序。 您可以点击任意列标题以更改列表的排序方式。
在 Instance View 中,每个实例都包含以下信息:
将堆转储另存为 HPROF
在捕获堆转储后,仅当分析器运行时才能在 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
复制代码
分析内存的技巧
使用 Memory Profiler 时,您应对应用代码施加压力并尝试强制内存泄漏。 在应用中引发内存泄漏的一种方式是,先让其运行一段时间,然后再检查堆。 泄漏在堆中可能逐渐汇聚到分配顶部。 不过,泄漏越小,您越需要运行更长时间的应用才能看到泄漏。
您还可以通过以下方式之一触发内存泄漏:
提示: 您还可以使用 monkeyrunner 测试框架执行上述步骤。
利用 Network Profiler 检查网络流量
Network Profiler 能够在时间线上显示实时网络活动,包括发送和接收的数据以及当前的连接数。 这便于您查看应用传输数据的方式和时间,并据此对底层代码进行适当优化。点击 Android Profiler 窗口中的 NETWORK 时间线中的任意位置即可打开 Network Profiler 。
为什么应分析应用的网络活动
当您的应用向网络发出请求时,设备必须使用高功耗的移动或 WLAN 无线装置来收发数据包。无线装置不仅要消耗电力来传输数据,还需要消耗额外的电力来开启并且不锁定屏幕。
使用 Network Profiler,您可以查找频繁出现的短时网络活动峰值,这意味着您的应用需要经常打开无线装置,或需要长时间不锁定屏幕以处理集中出现的大量短时请求。这种模式说明您可以通过批量处理网络请求,减少必须开启无线装置来发送或接收数据的次数,从而优化应用,改善电池续航表现。这种方式还能让无线装置调整到低能耗模式,延长批量处理请求之间的间隔时间,节省能耗。
要详细了解优化应用网络活动 的相关技巧,请参阅 减少网络耗电量 。
Network Profiler 概览
Network Profiler 的默认视图如下图所示: 窗口的顶部的①处,可以看见wifi无线信号的强弱,在时间线上可以在②处点击和拖动一部分的时间线来检测流量,然后在窗口③中会显示所选时间段内收发的文件,包括文件名,大小,类型,状态和花费时间,你可以对窗口③的列表根据列来进行排序。还可以查看所选时间段的详细拆分,拆分的timeline可以显示文件是什么时候收发的,点击窗口3的其中一个文件,可以在窗口④中查看文件的详细信息。通过切换窗口④上方标签可以查看响应数据、标题信息和调用堆栈。
注: 必须启用高级分析才能从时间线中选择要检查的片段,查看发送和接收的文件列表,或查看有关所发送或接收的选定文件的详细信息。 要启用高级分析,请参阅 启用高级分析 。
排查网络连接问题
如果 Network Profiler 检测到流量值,但无法识别任何受支持的网络请求,您会收到以下错误消息:
" Network Profiling Data Unavailable: There is no information for the network traffic you've selected."
Network Profiler 目前只支持 HttpURLConnection 和 OkHttp 网络连接库。如果您的应用使用的是其他网络连接库,则可能无法在 Network Profiler 中查看网络活动。 如果您收到这条错误消息,但您的应用确实使用了 HttpURLConnection 或 OkHttp,请 报告错误 或 搜索 Issue Tracker ,在与您的问题有关的现有报告中加入您的反馈。 此外,您还可以利用以下资源请求提供关于其他库的支持。