批量跟踪分析

使用 ProfilingManager 收集多个轨迹文件后,逐个探索这些轨迹文件以查找性能问题变得不切实际。借助批量轨迹分析,您可以同时查询轨迹数据集,以执行以下操作:

  • 识别常见的性能回归。
  • 计算统计分布(例如 P50、P90、P99 延迟时间)。
  • 查找多个轨迹中的模式。
  • 查找离群轨迹,以便了解和调试性能问题。

本部分演示了如何使用 Perfetto Python 批处理轨迹处理器来分析一组本地存储的轨迹中的启动指标,并找到异常轨迹以进行更深入的分析。

设计查询

执行批量分析的第一步是创建 PerfettoSQL 查询。

在本部分中,我们将展示一个用于衡量应用启动延迟时间的查询示例。具体而言,您可以测量从 activityStart 到生成第一个帧(即首次出现 Choreographer#doFrame slice)的持续时间,以测量应用启动延迟时间(在应用控制范围内)。图 1 显示了要查询的部分。

轨迹的时间轴视图,突出显示从 activityStart 事件到第一个 Choreographer#doFrame 事件的持续时间。
图 1. 从 `activityStart` 到生成的第一帧的轨迹部分。
CREATE OR REPLACE PERFETTO FUNCTION find_slices(pattern STRING) RETURNS
TABLE (name STRING, ts LONG, dur LONG) AS
SELECT name,ts,dur FROM slice WHERE name GLOB $pattern;

CREATE OR REPLACE PERFETTO FUNCTION generate_start_to_end_slices(startSlicePattern STRING, endSlicePattern STRING, inclusive BOOL) RETURNS
TABLE(name STRING, ts LONG, dur LONG) AS
SELECT name, ts, MIN(startToEndDur) as dur
FROM
  (SELECT S.name as name, S.ts as ts, E.ts + IIF($inclusive, E.dur, 0) - S.ts as startToEndDur
  FROM find_slices($startSlicePattern) as S CROSS JOIN find_slices($endSlicePattern) as E
  WHERE startToEndDur > 0)
GROUP BY name, ts;

SELECT ts,name,dur from generate_start_to_end_slices('activityStart','*Choreographer#doFrame [0-9]*', true)

您可以在 Perfetto 界面中执行查询,然后使用查询结果生成调试轨道(图 2),并在时间轴中直观呈现该轨道(图 3)。

Perfetto 界面截图,显示了如何为启动查询创建调试轨道。
图 2. 为启动查询创建调试轨道。
Perfetto 界面中的时间轴视图,显示了针对启动查询生成的调试轨道。
图 3. 为启动查询生成的调试轨道。

设置 Python 环境

在本地计算机上安装 Python 及其所需的库:

pip install perfetto pandas plotly

创建批量轨迹分析脚本

以下示例脚本使用 Perfetto 的 Python BatchTraceProcessor 在多个轨迹中执行查询。

from perfetto.batch_trace_processor import BatchTraceProcessor
import glob
import plotly.express as px

traces = glob.glob('*.perfetto-trace')

if __name__ == '__main__':
    with BatchTraceProcessor(traces) as btp:
        query = """
        CREATE OR REPLACE PERFETTO FUNCTION find_slices(pattern STRING) RETURNS
        TABLE (name STRING, ts LONG, dur LONG) AS
        SELECT name,ts,dur FROM slice WHERE name GLOB $pattern;

        CREATE OR REPLACE PERFETTO FUNCTION generate_start_to_end_slices(startSlicePattern STRING, endSlicePattern STRING, inclusive BOOL) RETURNS
        TABLE(name STRING, ts LONG, dur LONG) AS
        SELECT name, ts, MIN(startToEndDur) as dur
        FROM
          (SELECT S.name as name, S.ts as ts, E.ts + IIF($inclusive, E.dur, 0) - S.ts as startToEndDur
          FROM find_slices($startSlicePattern) as S CROSS JOIN find_slices($endSlicePattern) as E
          WHERE startToEndDur > 0)
        GROUP BY name, ts;

        SELECT ts,name,dur / 1000000 as dur_ms from generate_start_to_end_slices('activityStart','*Choreographer#doFrame [0-9]*', true)
        """
        df = btp.query_and_flatten(query)

        violin = px.violin(df, x='dur_ms', hover_data='_path', title='startup time', points='all')
        violin.show()

了解脚本

运行 Python 脚本时,它会执行以下操作:

  1. 该脚本会在本地目录中搜索所有以 .perfetto-trace 为后缀的 Perfetto 轨迹,并将其用作分析的源轨迹。
  2. 它会运行批量轨迹查询,计算与从 activityStart 轨迹切片到应用生成的第一个帧的时间相对应的启动时间子集。
  3. 它使用小提琴图绘制以毫秒为单位的延迟时间,以直观呈现启动时间的分布。

解释结果

显示查询到的启动延迟时间分布情况的小提琴图。
图 4. 查询到的启动延迟的小提琴图。

执行脚本后,脚本会生成一个图表。在本例中,该图显示了具有两个明显峰值的双峰分布(图 4)。

接下来,找出这两个人群之间的差异。这有助于您更详细地检查各个轨迹。在此示例中,图表已设置好,以便您在将鼠标悬停在数据点(延迟时间)上时,可以识别轨迹文件名。然后,您可以打开高延迟组中的某个轨迹。

当您打开高延迟组中的轨迹(图 5)时,会发现启动期间运行的额外切片 MyFlaggedFeature(图 6)。相反,从低延迟时间群体(最左侧的峰)中选择轨迹会确认不存在相同的切片(图 7)。此比较表明,为部分用户启用的特定功能标志会触发回归。

突出显示高延迟时间轨迹的图表。
图 5. 小提琴图中的高延迟数据点。
一个突出显示了因 MyFlaggedFeature slice 而导致的高延迟启动的轨迹。
图 6. 具有额外“MyFlaggedFeature”切片的高延迟跟踪启动。
突出显示了不含 MyFlaggedFeature slice 的低延迟启动的轨迹。
图 7. 低延迟轨迹启动。

此示例展示了批量轨迹分析的众多使用方式之一。 其他用例包括从字段中提取统计信息以评估影响、检测回归等。