Android Studio 3.0 采用全新的 Android Profiler
窗口取代 Android Monitor
工具。 这些全新的分析工具可以提供关于应用 CPU
、内存
和网络活动
的实时数据。html
您能够执行基于样本的函数跟踪来记录代码执行时间、采集堆转储数据、查看内存分配,以及查看网络传输文件的详情。java
要打开 Android Profiler 窗口,请按如下步骤操做:android
Android Profiler 共享时间线的视图显示以下图所示: git
当您启动 Android Profiler 后,它会持续收集分析数据,直至您断开设备链接或点击 Close 。github
此共享时间线视图只显示时间线图表。 要使用详细分析工具,请点击与您想查看的性能数据对应的图表。 例如,要使用工具查看堆数据和跟踪内存分配,可点击 MEMORY 图表。shell
但并非全部分析数据均默承认见。 若是您看到一条消息,显示“Advanced profiling is unavailable for the selected process”,则需在运行配置中启用高级分析。编程
要显示高级分析数据,Android Studio 必须在您编译后的应用中插入监控逻辑。高级分析工具提供的功能包括:缓存
要启用高级分析,请按如下步骤操做:网络
如今从新构建并运行您的应用,便可获取完整的分析功能。但请注意,高级分析会减缓您的构建速度,因此仅当您想要开始分析应用时才启用此功能。oracle
注:对于原生代码,不可以使用高级分析功能。 若是您的应用是纯原生应用(不含 Java
Activity
类),则不可以使用高级分析功能。 若是您的应用使用了 JNI,则可以使用部分高级分析功能,例如 Event 时间线、GC Event、Java 分配对象和基于 Java 的网络活动,但不能检测基于原生的分配和网络活动。
使用 CPU Profiler 检查 CPU 活动 和函数跟踪 CPU Profiler 可帮助您实时检查应用的 CPU 使用率和线程活动,并记录函数跟踪,以便您能够优化和调试您的应用代码。点击 Android Profiler 窗口中的 CPU 时间线中的任意位置便可打开 CPU Profiler。
最大限度减小应用的 CPU 使用率具备许多优点,如提供更快更顺畅的用户体验,以及延长设备电池续航时间。 它还可帮助应用在各类新旧设备上保持良好性能。 与应用交互时,您可使用 CPU Profiler 监控 CPU 使用率和线程活动。 不过,如需了解应用如何执行其代码的详细信息,您应记录和检查函数跟踪。
对于应用进程中的每一个线程,您能够查看一段时间内执行了哪些函数,以及在其执行期间每一个函数消耗的 CPU 资源。 您还可使用函数跟踪来识别调用方和被调用方。 调用方指调用其余函数的函数,而被调用方是指被其余函数调用的函数。 您可使用此信息肯定哪些函数负责调用经常会消耗大量特定资源的任务,并尝试优化应用代码以免没必要要的工做。
若是您想收集可帮助您检查原生系统进程的详细系统级数据,并解决掉帧引发的界面卡顿,您应使用 systrace。
或者,若是您想导出您使用 Debug 类捕获的 .trace
文件,您应使用 Traceview。
当您打开 CPU Profiler 时,它将当即开始显示应用的 CPU 使用率和线程活动。CPU Profiler 的默认视图以下图所示:
如图所示,CPU Profiler 的默认视图包括如下内容:
- 绿色: 表示线程处于活动状态或准备使用 CPU。 即,它正在“运行中”或处于“可运行”状态。
- 黄色: 表示线程处于活动状态,但它正在等待一个 I/O 操做(如磁盘或网络 I/O),而后才能完成它的工做。
- 灰色: 表示线程正在休眠且没有消耗任何 CPU 时间。当线程须要访问尚不可用的资源时偶尔会发生这种状况。线程进入自主休眠或内核将此线程置于休眠状态,直到所需的资源可用。
- Sampled: 一个默认配置,在应用执行期间频繁捕获应用的调用堆栈。 分析器比较捕获的数据集以推导与应用代码执行有关的时间和资源使用信息。 基于“Sampled”的跟踪的固有问题是,若是应用在捕获调用堆栈后进入一个函数并在下一次捕获前退出该函数,则分析器不会记录该函数调用。 若是您对此类生命周期很短的跟踪函数感兴趣,您应使用“Instrumented”跟踪。
- Instrumented: 一个默认配置,在运行时设置应用以在每一个函数调用的开始和结束时记录时间戳。 它收集时间戳并进行比较,以生成函数跟踪数据,包括时间信息和 CPU 使用率。 请注意,与设置每一个函数关联的开销会影响运行时性能,并可能会影响分析数据,对于生命周期相对较短的函数,这一点更为明显。 此外,若是应用短期内执行大量函数,则分析器可能会迅速超出它的文件大小限制,且不能再记录更多跟踪数据。
- Edit configurations: 容许您更改上述“Sampled”和“Instrumented”记录配置的某些默认值,并将它们另存为自定义配置。 如需了解更多信息,请转到建立记录配置部分。
注: 分析器还会报告 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 视图,以下图所示:
- Wall clock time: 壁钟时间信息表示实际通过的时间。
- Thread time: 线程时间信息表示实际通过的时间减去线程没有消耗 CPU 资源的任意时间部分。对于任何给定函数,其线程时间始终少于或等于其壁钟时间。 使用线程时间可让您更好地了解线程的实际 CPU 使用率中有多少是给定函数消耗的。
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 的默认视图包括如下各项:
- 一个显示每一个内存类别使用多少内存的堆叠图表,如左侧的 y 轴以及顶部的彩色键所示。
- 虚线表示分配的对象数,如右侧的 y 轴所示。
- 用于表示每一个垃圾回收 Event 的图标。
不过,若是您使用的是运行 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 中,每一个实例都包含如下信息:
在捕获堆转储后,仅当分析器运行时才能在 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 可以在时间线上显示实时网络活动,包括发送和接收的数据以及当前的链接数。 这便于您查看应用传输数据的方式和时间,并据此对底层代码进行适当优化。点击 Android Profiler 窗口中的 NETWORK 时间线中的任意位置便可打开 Network Profiler。
当您的应用向网络发出请求时,设备必须使用高功耗的移动或 WLAN 无线装置来收发数据包。无线装置不只要消耗电力来传输数据,还须要消耗额外的电力来开启而且不锁定屏幕。
使用 Network Profiler,您能够查找频繁出现的短时网络活动峰值,这意味着您的应用须要常常打开无线装置,或须要长时间不锁定屏幕以处理集中出现的大量短时请求。这种模式说明您能够经过批量处理网络请求,减小必须开启无线装置来发送或接收数据的次数,从而优化应用,改善电池续航表现。这种方式还能让无线装置调整到低能耗模式,延长批量处理请求之间的间隔时间,节省能耗。
要详细了解优化应用网络活动 的相关技巧,请参阅减小网络耗电量。
Network Profiler 的默认视图以下图所示:
注: 必须启用高级分析才能从时间线中选择要检查的片断,查看发送和接收的文件列表,或查看有关所发送或接收的选定文件的详细信息。 要启用高级分析,请参阅启用高级分析。
若是 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,在与您的问题有关的现有报告中加入您的反馈。 此外,您还能够利用如下资源请求提供关于其余库的支持。