Android Studio CPU 性能剖析器可实时检查应用的 CPU 使用率和线程活动。你还可以检查方法跟踪记录、函数跟踪记录和系统跟踪记录中的详细信息。
系统跟踪数据:捕获精细的详细信息,以便检查应用与系统资源的交互情况。
方法和函数跟踪数据:对于应用进程中的每个线程,你可以了解一段时间内执行了哪些方法 (Java) 或函数 (C/C++),以及每个方法或函数在其执行期间消耗的 CPU 资源。你还可以使用方法和函数跟踪数据来识别调用方和被调用方。调用方是指调用其他方法或函数的方法或函数,而被调用方是指被其他方法或函数调用的方法或函数。你可以使用此信息来确定哪些方法或函数负责调用常常会消耗大量资源的特定任务,并优化应用的代码以避免不必要的工作。
记录方法跟踪数据时,您可以选择“sampled”或“instrumented”记录。记录函数跟踪数据时,只能使用“sampled”记录。
要打开 CPU Profiler,请按以下步骤操作:
当你打开 CPU Profiler 时,它会立即开始显示应用的 CPU 使用率和线程活动。你会看到类似于下图的一些内容:
CPU Profiler 的默认视图包括以下时间轴:
事件时间轴:显示应用中的 Activity 在其生命周期内不断转换而经历各种不同状态的过程,并指示用户与设备的交互,包括屏幕旋转事件。如需了解如何在搭载 Android 7.1(API 级别 25)及更低版本的设备上启用事件时间轴,请参阅启用高级分析。
CPU 时间轴:显示应用的实时 CPU 使用率(以占总可用 CPU 时间的百分比表示)以及应用当前使用的线程总数。此时间轴还显示其他进程(如系统进程或其他应用)的 CPU 使用率,以便您可以将其与您应用的使用率进行对比。您可以通过沿时间轴的水平轴移动鼠标来检查历史 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 所示。如果要检查其他线程的跟踪数据,请从线程活动时间轴上选择相应线程。
在开始记录跟踪信息之前,请为要捕获的分析信息选择适当的记录配置:
基于采样的跟踪存在一个固有的问题,那就是如果应用在捕获调用堆栈后进入一个方法且在下次捕获前退出该方法,则分析器不会记录该方法调用。如果您想要跟踪生命周期如此短的方法,应使用检测跟踪。
请注意,与检测每个方法关联的开销会影响运行时性能,并且可能会影响分析数据;对于生命周期相对较短的方法,这一点更为明显。此外,如果应用在短时间内执行大量方法,则分析器可能很快就会超出其文件大小限制,因而不能再记录更多跟踪数据。
在内部,此配置使用 simpleperf 跟踪应用的原生代码。如果要为 simpleperf 指定其他选项,如对特定设备 CPU 采样指定高精度采样持续时间,您可以从命令行使用 simpleperf。
使用此跟踪配置时,您可以通过检测代码来直观地标记分析器时间轴上的重要代码例程。要检测 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 标签提供方法跟踪数据或函数跟踪数据的图形表示形式,其中调用的时间段和时间在水平轴上表示,而其被调用方显示在垂直轴上。对系统 API 的调用显示为橙色,对应用自有方法的调用显示为绿色,对第三方 API(包括 Java 语言 API)的调用显示为蓝色。图 4 显示了一个调用图表示例,说明了给定方法或函数的 Self 时间、Children 时间和 Total 时间的概念。如需详细了解这些概念,请参阅有关如何使用 Top Down 和 Bottom Up 检查跟踪数据的部分。
图 4. 一个调用图表示例,说明了方法 D 的 Self 时间、Children 时间和 Total 时间。
提示:要跳转到某个方法或函数的源代码,请右键点击该方法或函数,然后选择 Jump to Source。从任何跟踪数据窗格标签中均可执行此操作。
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 标签显示一个调用列表,在该列表中展开方法或函数节点会显示它的被调用方。图 8 显示了图 4 中调用图表的自上而下图。图中的每个箭头都从调用方指向被调用方。
如图 8 所示,在 Top Down 标签中展开方法 A 的节点会显示它的被调用方,即方法 B 和 D。在此之后,展开方法 D 的节点会显示它的被调用方,即方法 B 和 C,依此类推。与 Flame chart 标签类似,“Top Down”树也汇总具有相同调用堆栈的完全相同的方法的跟踪信息。也就是说,Flame chart 标签提供 Top down 标签的图形表示形式。
Top Down 标签提供以下信息来帮助说明在每个调用上所花的 CPU 时间(时间也可表示为在选定范围内占线程总时间的百分比):
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 标签查看每个线程上发生的事件的详细信息。
要查看某个线程的详细信息,请在 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 时间轴导出跟踪文件,请执行以下操作:
要从 Sessions 窗格导出跟踪文件,请执行以下操作:
您可以导入 .trace 文件(使用 Debug API 或 CPU Profiler 创建的)。
要导入跟踪文件,请点击分析器中的 Start new profiler session 图标(加号)(Sessions 窗格中),然后选择 Load from file。
您可以检查 CPU Profiler 中导入的跟踪数据,就像检查直接在 CPU Profiler 中捕获的跟踪数据一样,但有下面几点不同:
在线程列表中,选择相应线程,例如main线程,选中后双击展开,这时我们就可以看到详细的方法调用情况以及耗时详情了。
如图:
提示:可以使用键盘按键”W“放大,使用”S"缩小视图。
如果我们在特定的方法中开启、结束检测,或者我们想分析APP的启动性能,使用上面的方法显然不够准确,我们如何来做呢?
我们可以使用 Debug API 让您的应用能够在 CPU Profiler 中开始和停止记录 CPU 活动。
在记录使用此 API 触发的 CPU 活动时,CPU Profiler 会将 Debug API 显示为活动的 CPU 记录配置。
注意:要使用 Debug API 控制 CPU 活动的记录,请将检测的应用部署到搭载 Android 8.0(API 级别 26)或更高版本的设备上。
要在应用启动过程中自动开始记录 CPU 活动,请执行以下操作:
如图:
本文介绍了Android Studio CPU profiler性能分析工具的使用,以及如何使用Android Studio CPU profiler解决我们的APP耗时,卡顿等问题。
PS:性能优化专栏:《Android性能》持续更新中……