Android Studio CPU profiler性能分析工具介绍和使用详解

Android Studio CPU profiler性能分析工具介绍和使用详解


CPU profiler介绍

Android Studio CPU 性能剖析器可实时检查应用的 CPU 使用率和线程活动。你还可以检查方法跟踪记录、函数跟踪记录和系统跟踪记录中的详细信息。

使用CPU profiler来解决哪些性能问题

  1. 我们可以使用CPU profiler来分析CPU耗时问题,解决由于CPU资源消耗而产生的性能问题。
  2. 我们可以使用CPU profiler来查看主线程中每个方法的耗时情况,以及每个方法的调用栈,可以很方便的分析卡顿产生的原因,以及定位到具体的代码方法。
  3. 我们可以使用它来进行启动优化分析,查看APP启动时的耗时问题。
  4. 我们可以使用它来查看线程的执行情况,定位线程的CPU资源占用等问题。

CPU Profiler可以记录和显示以下性能数据:

  • 系统跟踪数据:捕获精细的详细信息,以便检查应用与系统资源的交互情况。

  • 方法和函数跟踪数据:对于应用进程中的每个线程,你可以了解一段时间内执行了哪些方法 (Java) 或函数 (C/C++),以及每个方法或函数在其执行期间消耗的 CPU 资源。你还可以使用方法和函数跟踪数据来识别调用方和被调用方。调用方是指调用其他方法或函数的方法或函数,而被调用方是指被其他方法或函数调用的方法或函数。你可以使用此信息来确定哪些方法或函数负责调用常常会消耗大量资源的特定任务,并优化应用的代码以避免不必要的工作。

记录方法跟踪数据时,您可以选择“sampled”或“instrumented”记录。记录函数跟踪数据时,只能使用“sampled”记录。

CPU profiler的使用

打开CPU profiler

要打开 CPU Profiler,请按以下步骤操作:

  1. 连接真机或虚机设备,确保可以进行ADB调试,依次选择 View > Tool Windows > Profiler 或点击工具栏中的 Profile 图标。
  2. 当APP运行起来后,点击 CPU 时间轴上的任意位置以打开 CPU Profiler。

CPU Profiler视图介绍

当你打开 CPU Profiler 时,它会立即开始显示应用的 CPU 使用率和线程活动。你会看到类似于下图的一些内容:
在这里插入图片描述

CPU Profiler 的默认视图包括以下时间轴:

  1. 事件时间轴:显示应用中的 Activity 在其生命周期内不断转换而经历各种不同状态的过程,并指示用户与设备的交互,包括屏幕旋转事件。如需了解如何在搭载 Android 7.1(API 级别 25)及更低版本的设备上启用事件时间轴,请参阅启用高级分析

  2. CPU 时间轴:显示应用的实时 CPU 使用率(以占总可用 CPU 时间的百分比表示)以及应用当前使用的线程总数。此时间轴还显示其他进程(如系统进程或其他应用)的 CPU 使用率,以便您可以将其与您应用的使用率进行对比。您可以通过沿时间轴的水平轴移动鼠标来检查历史 CPU 使用率数据。

  3. 线程活动时间轴:列出属于应用进程的每个线程,并使用下面列出的颜色在时间轴上指示它们的活动。记录跟踪数据后,您可以从此时间轴上选择一个线程,以在跟踪数据窗格中检查其数据。

    • 绿色:表示线程处于活动状态或准备使用 CPU。也就是说,它处于正在运行或可运行状态。
    • 黄色:表示线程处于活动状态,但它正在等待一项 I/O 操作(如磁盘或网络 I/O),然后才能完成它的工作。
    • 灰色:表示线程正在休眠且没有消耗任何 CPU 时间。当线程需要访问尚不可用的资源时,有时会发生这种情况。在这种情况下,要么线程自主进入休眠状态,要么内核将线程置于休眠状态,直到所需的资源可用。

CPU Profiler 还会报告 Android Studio 和 Android 平台添加到应用进程的线程的 CPU 使用率,这些线程包括 JDWP、Profile Saver、Studio:VMStats、Studio:Perfa 和 Studio:Heartbeat 等(然而,它们在线程活动时间轴上显示的确切名称可能有所不同)。Android Studio 将报告此数据,以便您确定线程活动和 CPU 使用率实际在何时是由您的应用的代码引发。

记录跟踪数据

要开始记录跟踪数据,请从 CPU Profiler 顶部的下拉菜单中选择记录配置,然后点击 Record。

在这里插入图片描述

如图,CPU Profiler 显示了正在进行的记录的状态、持续时间和类型:

在这里插入图片描述

与您的应用交互,然后在完成时点击 Stop。分析器将自动选择记录的时间范围,并在跟踪数据窗格中显示其跟踪信息,如图 3 所示。如果要检查其他线程的跟踪数据,请从线程活动时间轴上选择相应线程。
在这里插入图片描述

  1. 选定范围:确定要在跟踪数据窗格中检查所记录时间的哪一部分。当您首次记录跟踪数据时,CPU Profiler 会自动在 CPU 时间轴上选择记录的完整长度。要仅检查所记录时间范围的一部分的跟踪数据,请拖动突出显示区域的边缘。
  2. 时间戳:指示所记录跟踪数据的开始和结束时间(相对于分析器开始收集 CPU 使用率信息的时间)。要选择完整的记录,请点击时间戳。
  3. 跟踪数据窗格:显示您选择的时间范围和线程的跟踪数据。只有在您至少记录一条跟踪数据后,才会显示此窗格。在此窗格中,您可以选择如何查看每个堆栈轨迹(使用跟踪数据标签),以及如何测量执行时间(使用时间参考下拉菜单)。
  4. 跟踪数据窗格标签:选择如何显示跟踪数据详细信息。
  5. 时间参考菜单:选择以下选项之一,以确定如何测量每次调用的时间信息:
    • Wall clock time:时间信息表示实际经过的时间。
    • Thread time:时间信息表示实际经过的时间减去线程在该时间内没有消耗 CPU 资源的所有部分。对于任何给定的调用,其线程时间始终小于或等于其挂钟时间。使用线程时间可以让您更好地了解线程的实际 CPU 使用率中有多少是给定方法或函数消耗的。
  6. 过滤器:按函数、方法、类或软件包名称过滤跟踪数据。例如,如果您要快速识别与特定调用相关的跟踪数据,请点击 Filter 图标或按 Ctrl + F(在 Mac 上,按 Command + F 键),然后在搜索字段中输入相应的名称。在 Call chart 和 Flame chart 标签中,会突出显示包含符合搜索查询条件的调用、软件包或类的调用堆栈。在 Top down 和 Bottom up 标签中,这些调用堆栈优先于其他跟踪结果。您还可以通过勾选搜索字段旁边的相应框来启用以下选项:
    • Regex:要在您的搜索中包含正则表达式,请使用此选项。
    • Match case:如果您的搜索区分大小写,请使用此选项。

选择记录配置

在开始记录跟踪信息之前,请为要捕获的分析信息选择适当的记录配置:

  • 对 Java 方法采样:在应用的 Java 代码执行期间,频繁捕获应用的调用堆栈。分析器会比较捕获的数据集,以推导与应用的 Java 代码执行有关的时间和资源使用信息。

基于采样的跟踪存在一个固有的问题,那就是如果应用在捕获调用堆栈后进入一个方法且在下次捕获前退出该方法,则分析器不会记录该方法调用。如果您想要跟踪生命周期如此短的方法,应使用检测跟踪。

  • 跟踪 Java 方法:在运行时检测应用,以在每个方法调用开始和结束时记录一个时间戳。系统会收集并比较这些时间戳,以生成方法跟踪数据,包括时间信息和 CPU 使用率。

请注意,与检测每个方法关联的开销会影响运行时性能,并且可能会影响分析数据;对于生命周期相对较短的方法,这一点更为明显。此外,如果应用在短时间内执行大量方法,则分析器可能很快就会超出其文件大小限制,因而不能再记录更多跟踪数据。

  • 对 C/C++ 函数采样:捕获应用的原生线程的采样跟踪数据。要使用此配置,您必须将应用部署到搭载 Android 8.0(API 级别 26)或更高版本的设备上。

在内部,此配置使用 simpleperf 跟踪应用的原生代码。如果要为 simpleperf 指定其他选项,如对特定设备 CPU 采样指定高精度采样持续时间,您可以从命令行使用 simpleperf。

  • 跟踪系统调用:捕获精细的详细信息,以便您检查应用与系统资源的交互情况。您可以检查线程状态的确切时间和持续时间、直观地查看所有核心的 CPU 瓶颈在何处,并添加要分析的自定义跟踪事件。当您排查性能问题时,此类信息至关重要。要使用此配置,您必须将应用部署到搭载 Android 7.0(API 级别 24)或更高版本的设备上。

使用此跟踪配置时,您可以通过检测代码来直观地标记分析器时间轴上的重要代码例程。要检测 C/C++ 代码,请使用原生跟踪 API(由 trace.h 提供)。要检测 Java 代码,请使用 Trace 类。

此跟踪配置在 systrace 的基础上构建而成。您可以使用 systrace 命令行实用程序指定 CPU Profiler 中提供的选项以外的其他选项。systrace 提供的其他系统级数据可帮助您检查原生系统进程并排查丢帧或帧延迟问题。

分析跟踪数据

CPU Profiler 中的跟踪数据窗格提供多个标签,供您选择如何查看所记录跟踪数据的信息。

对于方法跟踪数据和函数跟踪数据,您可以从 Call Chart、Flame Chart、Top Down 和 Bottom Up 标签中进行选择。对于系统跟踪数据,您可以从 Trace Events、Flame Chart、Top Down 和 Bottom Up 标签中进行选择。

使用“Call Chart”标签检查跟踪数据

Call Chart 标签提供方法跟踪数据或函数跟踪数据的图形表示形式,其中调用的时间段和时间在水平轴上表示,而其被调用方显示在垂直轴上。对系统 API 的调用显示为橙色,对应用自有方法的调用显示为绿色,对第三方 API(包括 Java 语言 API)的调用显示为蓝色。图 4 显示了一个调用图表示例,说明了给定方法或函数的 Self 时间、Children 时间和 Total 时间的概念。如需详细了解这些概念,请参阅有关如何使用 Top Down 和 Bottom Up 检查跟踪数据的部分。
在这里插入图片描述

图 4. 一个调用图表示例,说明了方法 D 的 Self 时间、Children 时间和 Total 时间。

提示:要跳转到某个方法或函数的源代码,请右键点击该方法或函数,然后选择 Jump to Source。从任何跟踪数据窗格标签中均可执行此操作。

使用“Flame Chart”标签检查跟踪数据

Flame Chart 标签提供一个倒置的调用图表,用来汇总完全相同的调用堆栈。也就是说,将具有相同调用方顺序的完全相同的方法或函数收集起来,并在火焰图中将它们表示为一个较长的横条(而不是将它们显示为多个较短的横条,如调用图表中所示)。这样更方便您查看哪些方法或函数消耗的时间最多。不过,这也意味着,水平轴不代表时间轴,而是表示执行每个方法或函数所需的相对时间量。

为帮助说明此概念,不妨考虑图 5 中的调用图表。请注意,方法 D 多次调用 B(B1、B2 和 B3),其中一些对 B 的调用也调用了 C(C1 和 C3)。

在这里插入图片描述

图 5. 一个调用图表,其中的多个方法调用有着共同的调用方顺序。

由于 B1、B2 和 B3 具有相同的调用方顺序 (A → D → B),因此将它们汇总在一起,如图 6 所示。同样,也将 C1 和 C3 汇总在一起,因为它们也具有相同的调用方顺序 (A → D → B → C)。请注意,C2 不包括在内,因为它具有不同的调用方顺序 (A → D → C)。
在这里插入图片描述

图 6. 汇总具有相同调用堆栈的完全相同的方法。

汇总的调用用于创建火焰图,如图 7 所示。请注意,对于火焰图中的任何给定调用,先显示的是消耗最多 CPU 时间的被调用方。

在这里插入图片描述

图 7. 图 5 中所示调用图表的火焰图表示形式。

使用“Top Down”和“Bottom Up”检查跟踪数据

Top Down 标签显示一个调用列表,在该列表中展开方法或函数节点会显示它的被调用方。图 8 显示了图 4 中调用图表的自上而下图。图中的每个箭头都从调用方指向被调用方。

如图 8 所示,在 Top Down 标签中展开方法 A 的节点会显示它的被调用方,即方法 B 和 D。在此之后,展开方法 D 的节点会显示它的被调用方,即方法 B 和 C,依此类推。与 Flame chart 标签类似,“Top Down”树也汇总具有相同调用堆栈的完全相同的方法的跟踪信息。也就是说,Flame chart 标签提供 Top down 标签的图形表示形式。

Top Down 标签提供以下信息来帮助说明在每个调用上所花的 CPU 时间(时间也可表示为在选定范围内占线程总时间的百分比):

  • Self:方法或函数调用在执行自己的代码(而非被调用方的代码)上所花的时间,如图 4 中的方法 D 所示。
  • Children:方法或函数调用在执行它的被调用方(而非自己的代码)上所花的时间,如图 4 中的方法 D 所示。
  • Total:方法的 Self 时间和 Children 时间的总和。这表示应用在执行调用上所花的总时间,如图 4 中的方法 D 所示。
    在这里插入图片描述

Bottom Up 标签显示一个调用列表,在该列表中展开函数或方法节点会显示它的调用方。沿用图 8 中所示的跟踪数据示例,图 9 提供了方法 C 的“Bottom Up”树。在“Bottom Up”树中打开方法 C 的节点会显示它独有的各个调用方,即方法 B 和 D。请注意,尽管 B 调用 C 两次,但在“Bottom Up”树中展开方法 C 的节点时,B 仅显示一次。在此之后,展开 B 的节点会显示它的调用方,即方法 A 和 D。

Bottom Up 标签用于按照消耗的 CPU 时间由多到少(或由少到多)的排序对方法或函数排序。您可以检查每个节点以确定哪些调用方在调用这些方法或函数上所花的 CPU 时间最多。与“Top Down”树相比,“Bottom Up”树中每个方法或函数的时间信息参照的是每个树顶部的方法(顶部节点)。CPU 时间也可表示为在该记录期间占线程总时间的百分比。下表有助于说明如何解释顶部节点及其调用方(子节点)的时间信息。
在这里插入图片描述

注意:对于给定的记录,当分析器达到文件大小限制时,Android Studio 会停止收集新数据(不过,不会停止记录)。在执行检测跟踪时,这种情况通常发生得更快,因为与采样跟踪相比,此类跟踪会在更短的时间内收集更多的数据。如果您将检查时间范围延长至达到限制后的记录期间,则跟踪数据窗格中的时间数据不会发生变化(因为没有新数据可用)。此外,当您仅选择没有数据可用的记录部分时,对于时间信息,跟踪数据窗格将显示 NaN。

使用“Trace Events”标签检查系统跟踪数据

检查系统跟踪数据时,您可以使用 Trace Events 标签查看每个线程上发生的事件的详细信息。

要查看某个线程的详细信息,请在 Threads 窗格中选择该线程。这样将在 Kernel 窗格中突出显示该线程在每个 CPU 核心上的活动,并在 Trace Events 标签中显示该线程的事件。在 Trace Events 标签中将鼠标指针悬停在某个事件上可查看该事件的名称以及在每种状态下所花的时间。

例如,在图 10 中,在 Threads 窗格中选择了 RenderThread,在 Kernel 窗格中突出显示了该线程在 CPU 0 和 CPU 1 上的活动,并在 Trace Events 标签中显示了在特定事件上所花的时间。
在这里插入图片描述

图 10. 查看渲染线程的 CPU 活动和跟踪事件。

如需详细了解如何检查系统跟踪信息,请参阅 systrace 文档的调查界面性能问题部分。

检查帧渲染数据

您可以检查应用在主线程和 RenderThread 上渲染每个帧所用的时间,以调查导致界面卡顿和帧速率较低的瓶颈。

要查看帧渲染数据,请使用可让您跟踪系统调用的配置记录跟踪记录。记录跟踪数据后,在名为 FRAMES 的部分下查找有关每个帧的信息,如图 11 所示。
在这里插入图片描述

图 11. 每个所用时间超过 16 毫秒的帧都以红色显示。

性能数据的导出和导入

导出跟踪数据

使用 CPU Profiler 记录 CPU 活动后,您可以将相应数据导出为 .trace 文件,以便与他人共享或日后进行检查。

要从 CPU 时间轴导出跟踪文件,请执行以下操作:

  1. 在 CPU 时间轴上,右键点击要导出的记录的方法跟踪数据或系统跟踪数据。
  2. 从菜单中选择 Export trace。
  3. 浏览到要将文件保存到的位置,指定文件名,然后点击 OK。

要从 Sessions 窗格导出跟踪文件,请执行以下操作:

  1. 在 Sessions 窗格中,右键点击要导出的记录的跟踪数据。
  2. 点击会话条目右侧的 Export method trace 或 Export system trace 按钮。
  3. 浏览到要将文件保存到的位置,指定文件名,然后点击 OK。

导入跟踪数据

您可以导入 .trace 文件(使用 Debug API 或 CPU Profiler 创建的)。

要导入跟踪文件,请点击分析器中的 Start new profiler session 图标(加号)(Sessions 窗格中),然后选择 Load from file。

您可以检查 CPU Profiler 中导入的跟踪数据,就像检查直接在 CPU Profiler 中捕获的跟踪数据一样,但有下面几点不同:

  1. CPU 活动未显示在 CPU 时间轴上。
  2. 线程活动时间轴仅指明了可在哪里获取各线程的跟踪数据,而未指明实际线程状态(如运行中、等待中或休眠中)。

如何准确的定位到方法

在线程列表中,选择相应线程,例如main线程,选中后双击展开,这时我们就可以看到详细的方法调用情况以及耗时详情了。

如图:

在这里插入图片描述

提示:可以使用键盘按键”W“放大,使用”S"缩小视图。

其他技巧

如果我们在特定的方法中开启、结束检测,或者我们想分析APP的启动性能,使用上面的方法显然不够准确,我们如何来做呢?

使用 Debug API 记录

我们可以使用 Debug API 让您的应用能够在 CPU Profiler 中开始和停止记录 CPU 活动。

  1. 在想要开启监控的地方调用startMethodTracing(String tracePath) 时,CPU Profiler 将开始记录;
  2. 在想要结束监控的地方调用stopMethodTracing() 时,CPU Profiler 将停止记录。

在记录使用此 API 触发的 CPU 活动时,CPU Profiler 会将 Debug API 显示为活动的 CPU 记录配置。

注意:要使用 Debug API 控制 CPU 活动的记录,请将检测的应用部署到搭载 Android 8.0(API 级别 26)或更高版本的设备上。

在应用启动过程中记录 CPU 活动

要在应用启动过程中自动开始记录 CPU 活动,请执行以下操作:

  1. 依次选择 Run > Edit Configurations。
  2. 在 Profiling 标签中,勾选 Start recording a method trace on startup 旁边的复选框。
  3. 从菜单中选择 CPU 记录配置。
  4. 点击 Apply。
  5. 依次选择 Run > Profile,将您的应用部署到搭载 Android 8.0(API 级别 26)或更高版本的设备上。

如图:

在这里插入图片描述

总结


本文介绍了Android Studio CPU profiler性能分析工具的使用,以及如何使用Android Studio CPU profiler解决我们的APP耗时,卡顿等问题。

ps:如果你喜欢本文,请随手点个赞吧😁~