Android perfetto - PerfettoSQL是什么?

81 阅读2分钟

1、Perfetto 数据模型

在开始学习 PerfettoSQL 之前,先了解 Perfetto 追踪的数据模型至关重要。Perfetto 使用一种关系型数据模型(表格和列)来存储性能追踪数据,PerfettoSQL 就是用来查询这些数据的。

1.1、Perfetto 数据库概述

  • Perfetto 的作用和架构:Perfetto 是 Google 提供的高效性能分析框架,用于收集、处理和分析性能数据。
  • Perfetto 数据存储格式:Perfetto 使用 SQLite 存储追踪数据,PerfettoSQL 就是对这些数据进行查询和分析的语言。

1.2、Perfetto 数据模型

  • 表结构:深入理解 Perfetto 中的各个表及其关系。了解以下表格及其用途:

    • slice:记录事件的执行片段(例如,某个线程的运行时间);
    • thread_state:记录线程状态变化(例如,线程从运行到睡眠);
    • sched:记录调度事件(例如,线程在 CPU 上的调度情况);
    • cpu:记录 CPU 相关的信息(例如,某个 CPU 执行了哪些任务);
    • args:存储事件的附加参数信息;
    • thread:提供线程的详细信息;
    • process:提供进程的详细信息;
  • 表间关系:理解表与表之间的关系,例如下图slice表通过arg_set_id关联到args表,sched表和cpu表通过ucpu 关联等。

执行SELECT * FROM sqlite_master;可以查到抓取的trace中包含的所有Perfetto表

2、PerfettoSQL简介

PerfettoSQL 是 Perfetto 中跟踪分析的基础。它是一种 SQL 方言,允许像查询数据库一样查询跟踪内容。SQL 中所有的语法都能在 PerfettoSQL 中正常运行。

  • SQL 基础:掌握基本的 SQL 查询语言,特别是 SELECT、WHERE、JOIN、GROUP BY 和 ORDER BY 等常用操作。

    • SELECT:选择要查询的列
    • FROM:指定查询的表
    • WHERE:设置查询条件
    • JOIN:关联不同的表
    • GROUP BYHAVING:进行分组和条件过滤
    • ORDER BY:排序查询结果
  • SQLite 特性:理解 SQLite 数据库的基本结构,如何查询表和查看表的结构(例如,使用sqlite_master)。

  • 查询语法:学习 Perfetto 中特有的 SQL 语法,如何结合多个表来进行复杂的性能分析。

    1. 简单查询

      • 查找所有事件的名字:

        SELECT name FROM slice;

      • 过滤掉某个特定事件的所有数据:

        SELECT * FROM slice WHERE name = 'measure';

    2. 多表连接(JOIN)

      • 获取与线程相关的事件:

        SELECT slice.name, thread_track.utid FROM slice JOIN thread_track ON thread_track.id = slice.track_id;

    3. 时间分析

      • 获取某个事件的持续时间:

        SELECT name, dur FROM slice WHERE name = 'measure'

    4. 分组和聚合

      • 计算每个线程的总耗时:

        SELECT thread_track.utid, SUM(slice.dur) AS total_duration FROM slice JOIN thread_track ON thread_track.id = slice.track_id GROUP BY thread_track.utid;

    5. 排序

      • 查找耗时最长的事件:

        SELECT name, MAX(dur) AS max_duration FROM slice GROUP BY name ORDER BY max_duration DESC LIMIT 5;

    6. 子查询

      • 查找每个线程的最大 measure 事件耗时:

        SELECT utid, MAX(dur) AS max_measure_time FROM (SELECT thread_track.utid, slice.dur FROM slice JOIN thread_track ON thread_track.id = slice.track_id WHERE slice.name = 'measure')

3、参考