
https://perfetto.dev/docs/analysis/sql-tableshttps://gugu-perf.github.io/perfetto-docs-zh-cn/docs/analysis/sql-tables.htmlPerfetto SQL的使用背景Perfetto 引入 SQL 能力是为了解决传统性能分析工具在处理海量 trace 数据时的痛点它的核心作用如下1. 解决传统分析的效率低传统工具手动翻时间轴、靠视觉估算指标面对数十万调度事件的大 trace 文件排查偶发问题可能耗时数天。而 Perfetto SQL 能直接将 trace 数据映射为 60 预定义表的 SQLite 数据库用标准 SQL 语法直接查询原本两天的调度延迟分析现在仅需15分钟就能完成。2. 实现精准量化的数据分析它支持直接计算平均延迟、标准差、CPU 占用率分布等量化指标替代过去依赖肉眼估算的模式。还能通过 WHERE 子句实现比 GUI 筛选器更灵活的精确过滤快速筛选出耗时超阈值的异常事件。3. 支持批量模式识别与深度关联通过 GROUP BY、聚合函数可以快速从海量数据中发现异常模式比如统计热点函数、识别高负载线程、关联系统事件与应用行为。还能跨进程、跨事件维度做关联分析挖掘出可视化界面难以发现的隐藏性能瓶颈。4. 降低分析门槛并支持自动化它基于通用的 SQL92/SQLite 语法开发者无需学习复杂的专用 API 就能上手打开 Perfetto UI 即可直接使用。还能和 Python 结合实现固定性能场景的自动化批量分析大幅减少重复人工操作的工作量。大白话讲解Perfetto sql存在必要性大家可能会有疑问为啥一定要sql进行查询量化分析直接看Perfetto分析不就好了么核心原因如下Perfetto直接看slice这种方式前提是Perfetto的项目时长都是比较有限而且你已经有很明确的分析位置很容易寻找到具体某个时间段瓶颈。但是在实际性能优化中你看要分析问题可能是一个时间段内的比如某个线程的调度延时等这种你抓某个时间点的就没有意义必须要进行统计量化才可以减少方差波动等。常见的一些table分类包含表核心用途时间片slice存储所有带起止时间的事件覆盖ATrace打点、自定义Track Event、系统派生事件是定位卡顿的核心表计数器counter、counter_track记录随时间变化的数值指标支持分析CPU频率、内存占用、功耗、业务计数器等动态数据线程与进程thread、process维护全量线程/进程元数据存储tid、pid、utid、upid、线程名、进程名等基础标识信息轨道track、thread_track、process_track定义事件的归属关系关联slice/counter到对应线程/进程支撑Perfetto UI的可视化轨道渲染调度状态thread_state、schedthread_state覆盖线程全状态流转Running/Sleeping/Waiting等sched仅记录线程占用CPU的Running区间CPU采样perf_sample、cpu_profile_stack_sample存储CPU Profiler的采样数据用于精准定位热点函数的CPU占用分布调用栈维表stack_profile_callsite、stack_profile_frame、stack_profile_mapping维护符号化的调用栈全链路信息需和采样表关联查询还原完整函数调用路径采集质量stats记录Trace采集过程中的数据丢失、缓冲区溢出、解析异常等问题用于校验Trace文件有效性Android Binder专属android_binder_txns专门存储Android系统的Binder IPC事务全量数据是分析跨进程通信性能的专属核心表直接Perfetto上拷贝现成的SQL语句再点击的track details再点击show query有了语句后然后执行Pefetto量化分析常用的一些SQL分享使用 SQL 进行量化分析点击左边的Query既可以。Perfetto 内置的 SQL 查询引擎是其强大功能之一允许开发者对 Trace 数据进行精确的聚合、筛选和分析。以下是一些常用的 CPU 分析查询。1. 计算各进程的 CPU 总时长此查询统计每个进程在所有 CPU 上运行的总时长按降序排列用于快速定位消耗 CPU 资源最多的进程。SELECT process.name, sum(dur)/ 1e9 AS total_cpu_time_s FROM sched JOIN thread ON sched.utidthread.utid JOIN process ON thread.upidprocess.upid GROUP BY process.name ORDER BY total_cpu_time_s DESC;结果2. 分析单个线程的时间状态分布此查询基于 thread_state 表可用于分析特定线程示例为 InputReader在各种状态下的时间分布从而判断其主要瓶颈。SELECT CASE state WHENRunningTHENRunningWHENRTHENRunnableWHENSTHENInterruptible SleepWHENDTHENUninterruptible SleepELSE state END AS human_state, sum(dur)/ 1e6 AS total_time_ms FROM thread_state WHERE utid(SELECT utid FROM thread WHERE nameInputReaderLIMIT1)GROUP BY human_state ORDER BY total_time_ms DESC;3. 查找特定时间段内 CPU 消耗最高的线程此查询用于分析特定场景如应用启动的 2-5s 时间段中消耗 CPU 时间最长的线程。SELECT thread.name, sum(dur)/ 1e9 AS cpu_time_s FROM sched JOIN thread ON sched.utidthread.utid -- 时间戳单位为纳秒可以自己加上 WHERE ts2e9 AND ts5e9 来取某一段时间 GROUP BY thread.name ORDER BY cpu_time_s DESC LIMIT20;4. 查看线程在各 CPU 核心上的运行时间分布此查询有助于了解一个线程的 CPU 亲和性以及它是否在预期的大小核上运行。SELECT cpu, sum(dur)/ 1e6 AS time_on_cpu_ms FROM sched WHERE utid(SELECT utid FROM thread WHERE nameInputReaderLIMIT1)GROUP BY cpu ORDER BY cpu;可以看出大部分时间在cpu0-1运行5.查询binder的调用耗时等情况INCLUDE PERFETTO MODULE android.binder;SELECTaidl_name,method_name,client_process,client_thread,client_dur/1e6ASclient_ms,server_process,server_thread,server_dur/1e6ASserver_ms,(server_ts-client_ts)/1e6ASdispatch_msFROMandroid_binder_txnsWHEREis_syncORDERBYclient_durDESCLIMIT20;原文干货视频地址https://mp.weixin.qq.com/s/KlCH37ZVweq0SMMmR29Shg