EN

loading
我做了什么

这篇文章只做一件事:把我长期维护、正在推进、已经公开和暂未公开的项目集中到一个地方。范围包括 Android 性能分析、Perfetto 工具、AI 自动化、iOS App、Android Demo、测试套件、博客系列、社群和各个平台账号。

第一次来到这个博客,可以按需求直接跳转:学 Android 性能分析,看 Perfetto / Systrace 系列;找工具项目,看 SmartPerfetto、TraceFix、Android App Memory Analysis;了解 AI 如何参与知识管理和日常工作,看 OpenClaw 与 AI Field Notes;联系我或查看其它平台账号,看文末。

项目按四条线划:性能分析方向有 SmartPerfetto、Android App Memory Analysis、TraceFix、Perfetto Auto-Pin 这类工具,以及 High Performance Friends Circle 测试平台;AI 与自动化方向有 OpenClaw、AI Field Notes、Gracker Skills、Open Design;个人 App 包括 100Years、iBattery 两个 iOS 项目和 Android 项目 Juju;内容项目则是博客和 Android Weekly 两处主阵地。下面每个项目都会注明状态:日常维护、近期重点、还是已经暂停。

Android Perfetto 系列 18:响应速度实战,从输入事件到首帧反馈

按钮按下后,按压态何时出现?滑动列表时,内容何时第一次跟着手指移动?这两个问题都要找到输入事件和对应的第一帧反馈;启动总耗时与后续动画帧率回答的是别的问题。

本文用 Perfetto 把 InputReader 读到事件、InputDispatcher 派发、App 处理、帧提交和 SurfaceFlinger 呈现分开计时。每一步的起止点要能回到 Trace 核对。

从 InputReader 的 read_time 到关联帧 present,可以得到系统内部延迟的候选值 estimated_input_to_present_ms。只有确认目标 layer、业务状态确实在那一帧发生视觉变化,才把它写成 input_to_present_ms。这段时间不包含触控 IC、驱动上报前延迟、显示扫描和面板响应。

点击和滑动还需要不同的终点定义:按压态、转场首帧和内容第一次位移不能混成一个数。App marker 能说明业务动作,高速相机可补外部可见时点。

Android Perfetto 系列 17:专项场景自动化、问题清单与平台体系

Camera 打开慢要区分 API 返回、HAL 首个 Buffer 和预览画面显示;Audio underrun 要看 App 写入与 mixer 周期是否稳定。这些事件分散在 App、系统服务、HAL 和调度轨道里,单列一张 Top slice 表还原不了顺序。

这里用 Camera 和 Audio 两个场景说明:先确认一次操作涉及哪些进程和线程,再按阶段或真实周期计算耗时,最后把异常时间点、来源轨道和质量限制写进报告。平台侧还要维护稳定的事件名和采集配置,下一次 Trace 才能复用查询。

Android Perfetto 系列 16:GPU、Power Counters 与硬件瓶颈分析

FrameTimeline 标出一帧晚了,主线程和 RenderThread 没有明显长任务,下一步可以查 GPU 工作与 fence。GPU 频率、电池电流和电源轨只能提供同一窗口的硬件状态,不能单独证明某个 App 帧为何晚呈现。

这篇把 GPU render stages、devfreq、电池计数器和电源轨放到同一段 Trace 窗口里,说明各自能回答什么、设备不支持时报告该怎么写。帧和线程的判读可接着第 7 篇与第 8 篇的例子读。

Counter 名称、单位和采样周期由设备 producer 决定。跨设备比较前先核对 descriptor;同一设备上也要确认目标帧与 GPU 工作是否能通过 token、layer 或 fence 关联。

Android Perfetto 系列 15:Boot Trace、长时间现场 Trace 与偶发问题抓取

开机慢、亮屏后偶发卡顿或几小时后才出现的音频断续,通常等不到工程师连上电脑再按「开始录制」。要保留问题发生前的调度、帧或音频事件,采集配置必须提前在设备上运行。

现场抓取要先确定触发点前后各保留多久,再选 Ring Buffer、周期写文件或 trigger。文件写出后,还要确认问题窗口没有被覆盖、关键数据源没有丢失。设备开机属于更早的特殊窗口,单独处理。

Android Perfetto 系列 14:heapprofd 与内存 Profiling

dumpsys meminfo 显示进程内存上涨,Java heap dump 却没有对应的对象增长时,下一步先查上涨落在 Native Heap、图形 Buffer,还是其他映射。若可疑部分来自 malloc/new,heapprofd 可以把分配与调用栈对应起来。

heapprofd 的分配、释放和调用栈记录能与业务事件放在同一条 Perfetto 时间轴上,便于核对一次操作前后哪些分配仍未释放。

heapprofd 是采样工具,看到的 native allocation 不能直接当作 RSS,也不覆盖 Java 对象引用或所有图形 backing 内存。先分清内存账,再决定是否抓 profile。我更倾向先用 meminfo 和 smaps 把上涨来源拆开,再打开 flamegraph;若涨的是 GraphicBuffer,盯着 malloc 调用栈改代码就找错了方向。

Android Perfetto 系列 13:Perfetto SDK、Track Event 与 App 现场 Trace

系统 Trace 能显示线程、CPU、帧和 Binder 等系统事件;播放器的 frame id、游戏 scene 名称或业务队列里的等待时间,需要应用自己提供。缺少这些标记时,一段主线程耗时只能定位到系统活动,难以对应业务阶段。

Perfetto SDK 的 Track Event 可以记录解码、纹理上传、队列深度和跨线程任务 ID。与系统轨道放在同一个时间窗口后,能先找到业务候选阶段,再用 RenderThread、GPU 和 FrameTimeline 验证它是否影响了可见帧。

接入前要先定事件名称、参数单位和采样频率。否则埋点虽然能显示在 UI 中,后续 SQL 仍无法稳定地按业务阶段聚合。

Android Perfetto 系列 12:Trace 数据流与丢失排查

一份 Trace 能在 UI 里打开、SQL 也查得到行,仍可能在采集中丢过数据。线程状态缺一段、进程名对不上、Track Event 只有 ID 没有名称时,先查数据丢在哪一层,再决定哪些分析还能继续。

SQL 只能度量留下来的事件。丢失发生在 ftrace、producer 共享内存还是 central buffer,影响的查询不同。看到一条 ftrace loss,我不会立刻扔掉整份 Trace;先查它影响的是调度、业务标记,还是帧数据。

下文沿事件从内核进入 Trace 文件的路径检查 ftrace、producer 共享内存、central buffer、增量状态和 flush。每一处都有对应的 stats 线索和下一次采集时可调整的配置。

Android Perfetto 系列 11:PerfettoSQL、Trace Processor 与回归检测

在 Perfetto UI 里框出问题窗口,看主线程、RenderThread 和 CPU 状态,再截几张图,单次定位很方便。换一份 Trace 或换一台设备,截图里的判断就难以按同一口径重算。我更关心的是:下次拿到同一类问题,还能不能算出可复查的数字。

PerfettoSQL 与 Trace Processor 可以把时间窗口、线程身份和耗时口径写进查询,再让 Python 对多份 Trace 执行同一段 SQL。这样复测版本时,能回到每份原始 Trace 核对数字。

下面从一条手工判断出发,逐步得到可批量执行的查询和结构化输出。示例代码需要替换目标进程、时间窗口和采集条件后再用于自己的场景。