2025 年 10 月 22 日,我给一个空的 Xcode 工程提交了第一次代码。一年出头,578 次提交之后,它成了 App Store 上的 100 Years Life。
这个 App 最初只有一个用户,就是我自己。我自己有一些基础病,平时又很喜欢运动,还是个数据党。体检报告、体脂秤、睡眠、运动,每一样我都留着数据。
问题是这些数据不在一处。
2025 年 10 月 22 日,我给一个空的 Xcode 工程提交了第一次代码。一年出头,578 次提交之后,它成了 App Store 上的 100 Years Life。
这个 App 最初只有一个用户,就是我自己。我自己有一些基础病,平时又很喜欢运动,还是个数据党。体检报告、体脂秤、睡眠、运动,每一样我都留着数据。
问题是这些数据不在一处。
SmartPerfetto 的版本更新以后集中写在这一篇,新的记录放在最前面。这里合并了此前几篇更新文章,主要保留版本范围、时间和重要变化。
目前整理到 v1.15.1(2026-10-06)。这是本文覆盖的版本,不代表项目的最新发行版;下载请看 GitHub Releases。
Android 内部机制的资料,网上不缺。AOSP、官方文档、博客、论文、trace 讨论,想找都找得到。麻烦的是各说各的版本:这篇是 Android 12 的结论,那篇没写版本,再一篇是某台机器上的现象。
AIW 想补的就是这个缺口。全称 Android Internal Wiki,中文书名是《Android 技术内幕:系统机制、性能优化与工具实战》,五部分二十六章,正文钉在 Android 17。仓库现已公开:
https://github.com/Gracker/android-internals-wiki
打开仓库能拿到的是二十六章正文、一份完整目录,和每周编一次的 EPUB。
这二十六章现在到了可以拿出来给人读的程度。读到哪一段和源码对不上,欢迎提 issue 或者 PR。
这篇文章只做一件事:把我长期维护、正在推进、已经公开和暂未公开的项目集中到一个地方。范围包括 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 两处主阵地。下面每个项目都会注明状态:日常维护、近期重点、还是已经暂停。
按钮按下后,按压态何时出现?滑动列表时,内容何时第一次跟着手指移动?这两个问题都要找到输入事件和对应的第一帧反馈;启动总耗时与后续动画帧率回答的是别的问题。
本文用 Perfetto 把 InputReader 读到事件、InputDispatcher 派发、App 处理、帧提交和 SurfaceFlinger 呈现分开计时。每一步的起止点要能回到 Trace 核对。
从 InputReader 的 read_time 到关联帧 present,可以得到系统内部延迟的候选值 estimated_input_to_present_ms。只有确认目标 layer、业务状态确实在那一帧发生视觉变化,才把它写成 input_to_present_ms。这段时间不包含触控 IC、驱动上报前延迟、显示扫描和面板响应。
点击和滑动还需要不同的终点定义:按压态、转场首帧和内容第一次位移不能混成一个数。App marker 能说明业务动作,高速相机可补外部可见时点。
Camera 打开慢要区分 API 返回、HAL 首个 Buffer 和预览画面显示;Audio underrun 要看 App 写入与 mixer 周期是否稳定。这些事件分散在 App、系统服务、HAL 和调度轨道里,单列一张 Top slice 表还原不了顺序。
这里用 Camera 和 Audio 两个场景说明:先确认一次操作涉及哪些进程和线程,再按阶段或真实周期计算耗时,最后把异常时间点、来源轨道和质量限制写进报告。平台侧还要维护稳定的事件名和采集配置,下一次 Trace 才能复用查询。
FrameTimeline 标出一帧晚了,主线程和 RenderThread 没有明显长任务,下一步可以查 GPU 工作与 fence。GPU 频率、电池电流和电源轨只能提供同一窗口的硬件状态,不能单独证明某个 App 帧为何晚呈现。
这篇把 GPU render stages、devfreq、电池计数器和电源轨放到同一段 Trace 窗口里,说明各自能回答什么、设备不支持时报告该怎么写。帧和线程的判读可接着第 7 篇与第 8 篇的例子读。
Counter 名称、单位和采样周期由设备 producer 决定。跨设备比较前先核对 descriptor;同一设备上也要确认目标帧与 GPU 工作是否能通过 token、layer 或 fence 关联。
开机慢、亮屏后偶发卡顿或几小时后才出现的音频断续,通常等不到工程师连上电脑再按「开始录制」。要保留问题发生前的调度、帧或音频事件,采集配置必须提前在设备上运行。
现场抓取要先确定触发点前后各保留多久,再选 Ring Buffer、周期写文件或 trigger。文件写出后,还要确认问题窗口没有被覆盖、关键数据源没有丢失。设备开机属于更早的特殊窗口,单独处理。
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 调用栈改代码就找错了方向。
系统 Trace 能显示线程、CPU、帧和 Binder 等系统事件;播放器的 frame id、游戏 scene 名称或业务队列里的等待时间,需要应用自己提供。缺少这些标记时,一段主线程耗时只能定位到系统活动,难以对应业务阶段。
Perfetto SDK 的 Track Event 可以记录解码、纹理上传、队列深度和跨线程任务 ID。与系统轨道放在同一个时间窗口后,能先找到业务候选阶段,再用 RenderThread、GPU 和 FrameTimeline 验证它是否影响了可见帧。
接入前要先定事件名称、参数单位和采样频率。否则埋点虽然能显示在 UI 中,后续 SQL 仍无法稳定地按业务阶段聚合。
一份 Trace 能在 UI 里打开、SQL 也查得到行,仍可能在采集中丢过数据。线程状态缺一段、进程名对不上、Track Event 只有 ID 没有名称时,先查数据丢在哪一层,再决定哪些分析还能继续。
SQL 只能度量留下来的事件。丢失发生在 ftrace、producer 共享内存还是 central buffer,影响的查询不同。看到一条 ftrace loss,我不会立刻扔掉整份 Trace;先查它影响的是调度、业务标记,还是帧数据。
下文沿事件从内核进入 Trace 文件的路径检查 ftrace、producer 共享内存、central buffer、增量状态和 flush。每一处都有对应的 stats 线索和下一次采集时可调整的配置。
在 Perfetto UI 里框出问题窗口,看主线程、RenderThread 和 CPU 状态,再截几张图,单次定位很方便。换一份 Trace 或换一台设备,截图里的判断就难以按同一口径重算。我更关心的是:下次拿到同一类问题,还能不能算出可复查的数字。
PerfettoSQL 与 Trace Processor 可以把时间窗口、线程身份和耗时口径写进查询,再让 Python 对多份 Trace 执行同一段 SQL。这样复测版本时,能回到每份原始 Trace 核对数字。
下面从一条手工判断出发,逐步得到可批量执行的查询和结构化输出。示例代码需要替换目标进程、时间窗口和采集条件后再用于自己的场景。
SmartPerfetto 已经完整开源。打开仓库能看到当前可运行的主干工程:Perfetto UI fork、后端 agentv3、MCP 工具、YAML Skill、场景策略、脚本和文档。没有保留私有核心模块,也没有只放一层 demo 壳。
这个项目来自一个很具体的日常场景:手里有一条 trace,Perfetto 已经把事实摆出来,但从事实到判断还要翻表、写 SQL、对线程、看 FrameTimeline、找 Binder 对端,再回到时间线上确认一遍。SmartPerfetto 想把这些重复动作固化成工具,让性能工程师把时间花在判断上。
它还处在开发阶段。现在放出来,是因为 trace 分析靠真实样本长出来:真实设备、真实厂商差异、真实业务 trace、真实 PR,都会改变 Skill 和策略该怎么写。等所有能力都稳定后再单向发布,反而会错过最需要样本的阶段。
如果你日常会打开 Perfetto 看滑动卡顿、启动、ANR、Binder、CPU 调度或渲染管线,SmartPerfetto 提供的是一个带 AI Assistant 的 Perfetto UI:加载 trace 后,用自然语言提问,后端查询 trace_processor_shell、调用 YAML Skill、组织证据,再把结论和数据表格流式显示在浏览器里。
项目地址:
普通试用只需要看主仓库。Gracker/perfetto 是 perfetto/ submodule 对应的前端 fork,主要给需要改 AI Assistant 插件 UI 的开发者使用。
前两篇技术文档更适合想看工程细节的读者:
前两篇把内部架构讲得比较细,但源码放出来以后,读者更关心的是仓库里到底有什么、能不能跑、哪些地方还没稳。这篇主要补开源这件事:开放了什么、当前能做什么、内部怎么分工、怎样在本地跑起来、哪些地方适合一起改。
以 2026 年 4 月 27 日郭明錤关于 OpenAI 手机的产业链消息为起点,从 Android 手机从业者视角,推演手机与 AI 融合之后的系统形态。
郭明錤这条消息最值得关注的地方,不在 2028 年量产这个时间点,也不在联发科、Qualcomm、立讯分别处在什么供应位置。
它把问题推到了系统层:
如果用户的主要目的从打开 App 转向完成任务,手机操作系统应该长什么样?
这句话听起来像 UI 变化,但站在 Android 从业者视角,它牵动的是一整套系统结构:Launcher、通知、权限、IPC、App 能力声明、模型运行时、TEE、端云同步、任务状态机、审计记录、支付确认、开发者分成,都会被重新审视。
过去几年,AI 手机的讨论大多停在功能层。厂商讲 AI 修图、AI 消除、AI 摘要、AI 搜索、AI 助手、AI 简报,这些都能放进现有 Android 或 iOS 架构里。
OpenAI 如果真的按 AI Agent 手机去做,它会把问题从“手机里还能塞多少 AI 功能”,推到“手机的第一入口还要不要从 App icon 开始”。
主线是:Agent OS 更像移动 OS 在图形界面之后的一次结构迁移。前台从 App 网格迁移到任务流,后台从 App 独占能力转为可授权能力,系统从管理进程和窗口转向管理任务、上下文与责任。
OpenAI 做手机不一定基于 Android,但概率很高,因为它能继承硬件适配、驱动、应用兼容和供应链经验。但如果 OpenAI 想完全按 Agent OS 设计第一屏、权限和任务流,它也可能走一条“Android 兼容但不完全是 Android”的路,甚至用 Linux 自建系统,再用 Web、云端执行和应用兼容层补齐服务。
不同 OS 选择会改变进入市场的速度,却不会改变 Agent OS 必须解决的五件事:
这五件事没有完成,AI 手机就只是“手机里装了一个 AI 助手”;它们一旦形成系统约束,手机才会朝 Agent OS 走。
这篇文章收集了《从 Trace 到洞察:SmartPerfetto AI Agent 的 Harness Engineering 实战》发布后收到的技术问题。它不重复正文的大段叙述,而是把最容易追问的设计点单独拆开。如果你已经读过正文,这里更适合作为二次阅读和交叉检索。
这篇文章记录了 SmartPerfetto 从零到可用过程中的关键技术决策。重点放在每次架构取舍背后的约束、失败案例和修正过程,而不是功能清单。如果你也在做 AI Agent 应用,或者在做 Perfetto 这类性能分析工具,这些工程折返点应该能直接参考。
文章按三层展开:先说清楚为什么 LLM 不能直接吃 Trace,包括上下文装不下、数值计算不可靠、领域知识用不上来三个原因;然后是从 Workflow 到 Agent 的迁移过程,附带 9 轮审查里挖出的冷启动 4 层联动 Bug 和 Ghost MCP Query 这类异步生命周期错配的具体案例;最后是 Scene Classification 按需加载、Artifact Store 控制返回数据量、三层验证从误判中迭代这三个关键决策为什么这么定。
上一篇 OpenClaw 实战复盘发出去之后,后台留言和群里讨论最多的就是这几个方向的问题:Token 消耗、能干什么、本地模型、隐私安全、使用体验。今天挑出被问频率最高的五个,一个一个说清楚。

最近这段时间,我一直在本地重度使用 OpenClaw。最开始我把它当成一个 AI 工具,但真正把它接进 Telegram、Obsidian、定时任务、本地模型和内容工作流之后,我发现它更像一套持续运转的工作系统。它能接消息、调工具、跑定时任务、调用不同模型、维护长期记忆、把结果回写 Obsidian,还能把复杂任务分发给别的 Agent。你如果只把它当聊天机器人,能用到的只是其中一小部分能力。
主线程上出现一段长 Binder 调用,慢的可能是服务端处理,也可能是事务派发、服务端线程排队或锁等待。这篇从一次调用出发,用 Perfetto 的 Binder 事件、线程状态和 Java monitor contention,把等待时间逐段分开。
这些信号需要在抓 Trace 时启用;看到主线程 Sleeping 或一个 futex 栈,只能确定它在等待,不能直接写成「Binder 慢」或「Java 锁慢」。
App 主线程没有按时处理一帧时,先分清它在 Running、Runnable 还是 Sleep;这三种状态对应的下一步调查完全不同。这篇用 Perfetto 的 CPU 调度、频率、空闲状态和采样数据,把「CPU 慢」拆成可核对的现象。
文中的核编号、频率和调度策略都要按目标设备确认。同一条线程运行在小核上,不足以单独证明调度错误。
在 Perfetto 里看到 vsync-app、vsync-sf 和 App 的 doFrame,很容易把三条轨道当成同一个时刻。这篇沿一次帧请求看 VSync 怎样从 SurfaceFlinger 的调度进入 App,接着怎样和 RenderThread、Buffer、FrameTimeline 对齐。
示例以 120 Hz 设备为主。相位配置、是否启用硬件 VSync,以及 App 是否请求下一帧都会改变轨道形态;本文先分清每个信号代表什么,再谈延迟。
版本说明(2026-10 核查):Java、JNI 和调度代码按
android-16.0.0_r1核对;app/appSf 的分工另引用 Android 13 源码。截图保留历史设备样例,不把它们视为 Android 16/17 的统一配置。代码省略外围状态时会明确说明,片段来自不同类,不能直接拼成可编译程序。
一次滑动卡顿,主线程可能在处理布局,也可能早已把绘制命令交给 RenderThread。这篇用 Perfetto 截图对照两条线程、Buffer 提交和 SurfaceFlinger,找出等待发生在哪一步。
先沿截图读一帧,再看 ActivityThread、RenderThread 和 BLASTBufferQueue 的职责。Trace 能缩小调查范围;帧最终是否上屏,还要核对 FrameTimeline 与合成侧记录。
120 Hz 把显示刷新间隔从 60 Hz 的约 16.67 ms 缩短到约 8.33 ms,但屏幕刷新率、App 产帧率和用户看到的帧并不是同一个数字。这篇从一份 Perfetto Trace 出发,解释三个数字怎样对应,以及高刷新率给渲染和功耗带来的取舍。
第 5 篇已经介绍 Choreographer 的回调顺序,这里重点看更短的显示周期。文中的设备截图只说明那次采集,不能代表所有 120 Hz 机型的调度配置。
本文介绍了 App 开发者不经常接触到但在 Android Framework 渲染链路中非常重要的一个类 Choreographer,包括 Choreographer 的引入背景、简介、部分源码解析、与 MessageQueue 的交互、在 APM 中的应用,以及手机厂商基于 Choreographer 的一些优化思路。
Choreographer 将待执行的帧回调与显示时序协调起来,而不是自行调整屏幕刷新率。以 120 Hz 为例,刷新间隔约 8.33 ms;是否能按时交付帧还取决于 CPU 调度、GPU、Buffer 和合成管线。应用按需请求回调,不是每个物理 Vsync 都要重新绘制。本文也会区分 FrameCallback、FrameMetrics、gfxinfo、Looper 和 Perfetto 各自能观察到的范围。
本篇是 Perfetto 系列文章的第四篇,如何使用 trace_processor_shell 在本地打开超过 2G 的大文件。在实际的问题分析过程中,我们经常会碰到非常大的 Trace 文件(大于 2GB),直接扔进 ui.perfetto.dev 可能会因浏览器内存限制而打不开;这里的限制是解析时的内存占用,并不是文件超过 2GB 就一定打不开。这时候我们就可以使用官方提供的 trace_processor_shell 工具来本地打开大文件。
写下这个系列时,Perfetto 在我的日常工作中已经基本取代 Systrace,我接触到的 OPPO、vivo 团队也在迁移。许多刚做 Android 性能优化的小伙伴觉得 Perfetto 界面眼花缭乱、功能复杂,希望我能把之前的 Systrace 文章用 Perfetto 再讲一遍。
本文为 Android App ANR 系列的第三篇,主要分享几个 ANR 的案例,系列文章目录如下
本文为 Android App ANR 系列的第二篇,主要分享 ANR 分析套路和关键 Log 介绍,系列文章目录如下
本文为 Android App ANR 系列的第一篇,主要是从系统的角度来剖析 Android ANR 的设计思想,系列文章目录如下
本篇是 Perfetto 系列文章的第三篇,前两篇介绍了 Perfetto 是什么以及 Perfetto Trace 怎么抓,本篇主要是在网页端打开 Perfetto Trace 之后,面对复杂的 Perfetto 信息该怎么看。
Android 官方将 Systrace 列为 legacy 工具,并推荐在 Android 10 及以上使用 Perfetto。写下本文时,Perfetto 在我的日常工作中已基本取代 Systrace,我接触到的 OPPO、vivo 团队也在迁移,因此用这个系列继续介绍如何观察 Android 系统。
技术核查:2026-10-14。 保留 2024 年界面与案例截图,快捷键和分析语义按官方文档及 v58.3(
11fbaed83636)源码补充。原始案例 Trace 未随文提供,图中的唤醒链和数值不当作新版本实测结果。
上一篇文章 Android Perfetto 系列 1:Perfetto 工具简介 介绍了 Perfetto 是什么,这篇简单介绍一下 Perfetto 的抓取。
Android 官方将 Systrace 列为 legacy 工具,并推荐在 Android 10 及以上使用 Perfetto。写下本文时,Perfetto 在我的日常工作中已基本取代 Systrace,我接触到的 OPPO、vivo 团队也在迁移,因此希望把原来的 Systrace 分析方法用 Perfetto 再讲一遍。
技术核查:2026-10-14。 本文以 Android 12+ 设备为主要示例,保留 2024 年截图;旧系统与新版 UI 的差异在对应段落说明。命令和配置按官方文档、脚本核对,本文未新增真机采集结果。
本篇是 Perfetto 系列文章的第一篇,主要是简单介绍 Perfetto 工具,包括 Perfetto 的历史、发展,以及 Perfetto 能做什么。
Android 官方将 Systrace 列为 legacy 工具,并推荐在 Android 10 及以上使用 Perfetto。写下本文时,Perfetto 在我的日常工作中已经基本取代 Systrace,我接触到的 OPPO、vivo 团队也在迁移。许多新接触 Android 性能优化的小伙伴面对复杂的界面和功能,希望我能把之前的 Systrace 文章用 Perfetto 来呈现。
技术核查:2026-10-14。 本文初稿和截图来自 2024 年,保留当时的使用体验。下面补充 Android 10/11/12 的数据源边界,以及 Perfetto v48.0/v49.0 的 UI 更新;具体可见数据仍取决于设备、采集配置和工具版本。
Perfetto 在我的日常工作中已基本替代旧的 Systrace 工作流。Android 官方建议在 Android 10 及以后使用 Perfetto,并将 Systrace 命令行工具列为 legacy。许多新接触 Android 性能优化的小伙伴觉得 Perfetto 的界面和功能复杂,希望我能把之前的 Systrace 文章用 Perfetto 重新呈现,于是有了这个系列。
今年偷个懒,找了个模版,主要从以下几个方面回顾过去一年:健康 / 锻炼、工作 / 职业、友情 / 社交、个人生活 / 家庭、学习 / 知识管理、旅游 / 文化、兴趣 / 创造、情绪 / 精神状况、财务状况。
内容更多是自己对于 2023 年的一个记录,算不上总结,文采也不好。不过很多事情,如果你不记录,就慢慢消失了。希望每次我翻看这篇记录的时候,都会感慨 2023 年真是丰富多彩的一年:有难忘的瞬间、有低谷、有朋自远方来、有去看大山大川;也会感慨有些事情做得很糟糕,如此这般其实可以做得更好;也会责备自己的懒惰,明明知道怎么做是对的,却因为懒惰没有去坚持。
各位看官一笑而过即可~
This is the historical English version of Yingyun’s article. See the Chinese original or the English-site version.
I am starting a series about the decisions involved in OS architecture. The same questions arise when designing other large software systems too.
My knowledge and experience have limits, and these views are subjective. There will be gaps. I would like to hear other views and see what I have missed.
本文是之前星球里 Yingyun 大佬的文章,由于星球已经关闭,所以把这个关于 OS 性能设计的系列文章发到博客上
Yingyun 是资深性能优化专家,他对于系统优化有非常深入的见解,本身在国内各个手机大厂都呆过,他本人的博客还在休整中,等休整好了我再发出来,目前他在我们的微信群里很活跃,对本文有什么建议或者意见,或者说想咨询问题的可以加我们的微信群(加我微信 553000664,备注博客加群,我会拉你进去)
新开系列文章,OS 架构设计中的各种考量因素。其实不止 OS,在设计任何大型软件都涉及到此类内容。
能力与知识面有限,而且还带了非常主观的看法,肯定有不足之处。希望听到不同的思路与观点,通过观点的碰撞进而达到更进一步的认知。
2023 年,公开研究披露了某款 Android App 中的漏洞利用代码和动态下发的 DEX。我想看看这些代码尝试调用哪些系统能力,于是有了这篇文章。当时准备仓促,有些代码没有仔细看;下面保留分析过程,并修正能从截图和 AOSP 源码确认的问题。原始文章和代码链接如下:
我不是安全方面的专家。关于漏洞背景,可以参考 Android 反序列化漏洞攻防史话。本文不复现漏洞链,也不把某个接口调用直接等同于已获得 root。
2022.3.25 ,周五晚上九点,The Performance 知识星球(付费版本)举办了第一次线上茶话会,3 位星球主理人 + 5 位星球嘉宾,50 多位球友参加,非常感谢各位!
第一次茶话会没有预设主题,预计 1 个小时就可以结束,结果聊了 2 个半小时,光是主理人和嘉宾的个人介绍就花了一个小时。平时大家在群里和星球里交流很多,但是通过语音在线交流还是第一次,再者大家的公司基本上涵盖了 Android 上下游:既有 App 大厂的大佬,也有一线手机厂商的系统大咖,也有芯片公司和造车新势力的资深专家。所以在每个人自我介绍的时候,会聊一些公司相关的东西,再发散一下,其他人再问一些问题,时间就过去了。
当时我们还计划不定期举办星球茶话会,把主题定得更明确,也邀请更多嘉宾一起聊,不局限于技术。考虑到隐私问题,这次没有录屏;下面的文字稿根据聊天内容部分还原,不涉及各位的隐私。
本文是 Systrace 线程 CPU 运行状态分析技巧系列的第三篇,本文主要讲了使用 Systrace 分析线程状态时遇到的 Sleep 与 Uninterruptible Sleep 状态的原因排查方法与优化方法,它们常见于正常等待,也可能拖慢关键路径,需要结合等待条件和依赖关系判断。
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。Systrace 基础和实战系列大家可以在 Systrace 基础知识 - Systrace 预备知识 或者 博客文章目录 这里看到完整的目录
本文是 Systrace 线程 CPU 运行状态分析技巧系列的第二篇,主要分析了 Systrace 中线程的 Running 状态出现的原因和 Running 过长时的一些优化思路。
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。Systrace 基础和实战系列大家可以在 Systrace 基础知识 - Systrace 预备知识 或者 博客文章目录 这里看到完整的目录
本文是 Systrace 线程 CPU 运行状态分析技巧系列的第一篇,主要分析了 Systrace 中线程的 Runnable 状态出现的原因和 Runnable 过长时的一些优化思路。
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。Systrace 基础和实战系列大家可以在 Systrace 基础知识 - Systrace 预备知识 或者 博客文章目录 这里看到完整的目录

In his book Hackers & Painters, Paul Graham asserted, “The disparity in the efficiency of languages is becoming more pronounced, hence the rising importance of profilers. Currently, performance analysis isn’t given the attention it deserves. Many still seem to hold onto the belief that the key to accelerating program execution lies in developing compilers that generate faster code. As the gap between code efficiency and machine performance widens, it will become increasingly apparent that enhancing the execution speed of application software hinges on having a good profiler to guide program development.” by Paul Graham, Hackers & Painters
Search for “Android optimization tools” and you’ll find plenty of articles. Many repeat the same material or go straight to instructions without explaining how the tools fit together. It is easy to come away thinking one tool can solve everything. Our team’s experience says otherwise: there is no silver bullet. Tools change, and familiar problems return in new forms. You still need to understand what is happening underneath.
We’ll start with the data we collect, how we collect it, and how we analyze it. Then we’ll look at Google’s traditional “big three” performance tools. We want you to understand the measurements as well as the tools, and save yourself some of the detours others have already taken.

Paul Graham 在其著作 <黑客与画家> 中断言:“不同语言的执行效率差距正变得越来越大,所以性能分析器(profiler)将变得越来越重要。目前,性能分析并没有受到重视。许多人好像仍然相信,程序运行速度提升的关键在于开发出能够生成更快速代码的编译器。代码效率与机器性能的差距正在不断加大,我们将会越来越清楚地看到,应用软件运行速度提升的关键在于有一个好的性能分析器帮助指导程序开发。”
by Paul Graham 黑客与画家
谷歌搜索 「Android 优化工具」,你会找到很多与此相关的内容。他们的问题在于要么是内容高度重复、要么是直接讲使用方法,很少会给你介绍整体性的架构,一不小心就会让人会种「一个工具搞定一切」的错误认知。以笔者团队的多年经验来看,在性能分析领域这种银弹级别的工具是不存在的。工具在发展,老问题会以新的方式变样出现,不掌握核心逻辑的话始终会让你浮于技术的表面。
本文首先系统性的梳理性能分析中的可观测性技术,它涵盖数据类型、抓取方法以及分析方法等三部分内容,之后是介绍谷歌提供的传统「三大件」分析工具。目的是想让你了解数据与测量的基本概念,以及与之对应的在安卓环境中可用的工具,这些可以让你少走一些弯路,直接复用前辈们的经验。
2021 已经过去,趁着元旦假期,回顾一下 2021,随意一些,想到哪里写哪里吧。主要是对 2021 年的一个回顾,以及 2022 年的展望,2021 年当了爸爸,换了工作(中间还居家无聊了好久),收获了更多的朋友,也算是过的还可以
不过在个人成长方面,甚至感觉有点退步,这让我觉得有点慌,学如逆水行舟,不进则退,2022 年是需要好好深耕的一年,希望能和看到这篇文章的同学一起进步,共勉
另外也盘点了一下知识分享相关的数据,分享了一下这方面的收入,个人新增和推荐的硬件、个人推荐的软件等,感兴趣的可以自取
最近读了一本新书:《打造流畅的 Android App》,京东链接:https://item.jd.com/10035215362170.html 。因为书名所以买了这本书,读完之后觉得有必要写一篇文章,让还没有买此书的同学了解一下
我个人的建议是:如果你是个老鸟,不建议买,这本书里面没有介绍太多原理性的东西,对于 Android 流畅性也没有一个比较全面的介绍;如果你是新手,这本书用来当做开阔视野 + 查漏补缺还可以,想更深入的了解 Android 流畅度还是差了点东西
之所以我会这么建议,是因为这本书确实没有讲太多性能或者流畅度相关的东西,也没有比较深入的原理部分,篇幅更多在讲静态代码审查、AS Profiler 的使用、App 架构、保活、网络性能优化、APK 大小优化、App 耗电等,内容也不深,浅尝辄止
Android 12 源码于 2021 年发布,我当时用来折腾的测试机是 Pixel 3 XL。本文保留那次实操记录,并将可复现的发布版示例固定为 android-12.0.0_r3。版本对应关系以 AOSP tags/build numbers 为准。
本文介绍这条历史分支的下载、编译和刷机。本地编译便于查看/修改系统源码、增加调试信息,主要用途如下:
在讨论 Android 性能问题的时候,卡顿、响应速度、ANR 常被放在一起。它们可能有共同原因,也可能同时出现,但不是按严重程度划分的三个等级。用户说“卡”,还需要分清是动画不连贯、操作后等得太久,还是系统触发了无响应判定。
动画或列表滚动的不连贯通常称为 Jank;应用启动、亮灭屏或场景切换耗时过长属于 响应慢(slow response / high latency);ANR 则由具体的系统超时条件触发。掉帧率、启动耗时和 ANR 率各有测量口径,分析时要分开。
本文是响应速度系列的第三篇,主要是讲在使用 Systrace 分析应用响应速度问题的时候,其中的一些延伸知识,包括启动速度测试、Log 输出解读、Systrace 状态解读、三方启动库等内容
在讨论 Android 性能问题的时候,卡顿、响应速度、ANR 常被放在一起。它们可能有共同原因,也可能同时出现,但不是按严重程度划分的三个等级。用户说“卡”,还需要分清是动画不连贯、操作后等得太久,还是系统触发了无响应判定。
动画或列表滚动的不连贯通常称为 Jank;应用启动、亮灭屏或场景切换耗时过长属于 响应慢(slow response / high latency);ANR 则由具体的系统超时条件触发。掉帧率、启动耗时和 ANR 率各有测量口径,分析时要分开。
本文是响应速度系列的第二篇,主要是以 Android App 冷启动为例,讲解如何使用 Systrace 来分析 App 冷启动
在讨论 Android 性能问题的时候,卡顿、响应速度、ANR 常会一起出现,部分原因也会重叠,但它们不是按严重程度划分的同一个问题。画面节奏异常、操作反馈延迟和具体超时机制触发的 ANR,需要分别确认。用户说“手机卡”或“App 卡”时,可以先把它当作宽泛的体验描述,再问清发生了什么、从哪个动作到哪个结果变慢。
动画播放或列表滑动不连贯,通常称为 Jank;应用启动、亮灭屏或场景切换耗时较长,可描述为 响应慢(slow response / high latency);ANR 则是 Application Not Responding。这些说法帮助组织问题,不是互斥分类;高延迟也可能同时伴随卡顿,ANR 还要按具体触发类型分析。
另外在 App 或者厂商内部,卡顿、响应速度、ANR 这几个性能指标都是有单独的标准的,比如 掉帧率、启动速度、ANR 率等,所以针对这些性能问题的分析和优化能力,对开发者来说就非常重要了
本文是响应速度系列的第一篇,主要讲响应速度相关的理论知识,包括性能工程概述、响应速度涉及到的知识点,以及分析方法。
不同的人对流畅性(卡顿掉帧)有不同的理解,对卡顿阈值也有不同的感知,所以有必要在开始这个系列文章之前,先把涉及到的内容说清楚,防止出现不同的理解,也方便大家带着问题去看这几篇问题,下面是一些基本的说明
不同的人对流畅性(卡顿掉帧)有不同的理解,对卡顿阈值也有不同的感知,所以有必要在开始这个系列文章之前,先把涉及到的内容说清楚,防止出现不同的理解,也方便大家带着问题去看这几篇问题,下面是一些基本的说明
不同的人对流畅性(卡顿掉帧)有不同的理解,对卡顿阈值也有不同的感知,所以有必要在开始这个系列文章之前,先把涉及到的内容说清楚,防止出现不同的理解,也方便大家带着问题去看这几篇问题,下面是一些基本的说明
技术群里的小伙伴发了一条微博, https://weibo.com/1808884742/IApbpEVQr, 博主 @王波粒 发现, Mate 30 Pro 有个很特别的现象(建议先去看一下视频)
这里讨论的是 2020 年观察到的一组差异:部分华为样机上的微博会在主页列表滑动中显示图片,而当时部分其他样机要等到停止后才显示。 这个现象不能推广到当前所有机型;相同客户端版本也可能受到配置、缓存和系统实现的影响。
同一个版本的微博,在不同手机上表现不一样,作为系统优化工程师,我还是想搞清楚的:是不是微博专门做了适配?具体改了什么?下面就从技术的角度来分析这个现象,看看我们能从里面学到什么。
2020 年 5 月 23 号凌晨 1 点 30 左右, 大量三星手机用户的手机出现死机, 无限重启、进 Recovery 等问题, 并且操作不当会导致数据丢失, 并且上了知乎的热点, 售后点更是人满为患
知乎的部分回答中, 大家更是对三星的家属送上了亲切的问候, 甚至有的人已经将这次事故与 Note7 事件、充电门、绿屏门事件相提并论, 甚至预言三星因此会退出国内市场 ; 有的人因为这个丢了 Offer, 有的人准备了很久的资源丢失, 有的人甚至直接把手机砸了…
作为一个 Android 开发者, 我并不想对三星落井下石, 我只想搞清楚到底是什么原因导致了这场事故, 以及我们能从里面学到什么 . 我认为既然是 Android 系统出了问题, 我们有必要从技术的角度来分析为什么会出现这样的问题
MIUI 12 的发布, 将之前一直是应用开发者和 Rom 开发者斗争最激烈的部分展示给了普通消费者, 让普通消费者也知道了这场斗争的细节, 正所谓 “魔高一尺道高一丈”, Rom 开发者由于有更高的代码修改权限, 始终占据着上风 ; App 开发者当然也不甘示弱, 各种保活拉起黑科技层出不穷,甚至 Google 都参与到了这部分斗争中, 居中调和, 制定各种规则来规范双方. 当然斗争对双方来说都算是好事, 毕竟任何一方完全的胜利都会导致 “狡兔死走狗烹,飞鸟尽良弓藏”
不过双方斗争的受害者无疑还是使用手机的消费者, App 如果斗争成功, 那么手机上各种后台进程乱跑, 杀不掉, 占用 CPU 和内存, 这不是消费者想看到的 ; 如果 Rom 开发者斗争成功, App 的体验必定会大打折扣, 各位 App 开发者应该深有体会.
从文章最后一段可以看到, 其实各个手机厂商对付这一套都有自己的策略, 基本上都可以搞定自启动和关联启动. 至于隐私, 李彦宏曾经说过 “中国人对隐私问题的态度更加开放,也相对来说没那么敏感。如果他们可以用隐私换取便利、安全或者效率。在很多情况下,他们就愿意这么做“ . 大家想想在微信里面复制一段话打开到淘宝就可以自动跳转到这个物品, 方不方便? 好不好用? 还想不想用? 剪贴板再借我看一看?
本文是 Systrace 系列文章的第五篇,主要是对 SurfaceFlinger 的工作流程进行简单介绍,介绍了 SurfaceFlinger 中几个比较重要的线程,包括 Vsync 信号的解读、应用的 Buffer 展示、卡顿判定等,由于 Vsync 这一块在 Systrace 基础知识 - Vsync 解读 和 Android 基于 Choreographer 的渲染机制详解 这两篇文章里面已经介绍过,这里就不再做详细的讲解了。
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
Medium 上 @MindOrks 发布了一篇 2020 年 Android 程序员的学习线路,鉴于一部分人无法阅读原文(你懂得原因),我把这篇文章的内容结合自己的 2020 年的学习计划,一起发出来,给大家一个参考
原文比较简单,并没有介绍为什么要推荐这些,只是单纯地列了一下知识点,我这边针对每个知识点做一些简单的介绍,有些知识点原文并没有提到,我会根据自己的理解加上,仅供参考
这篇文章主要针对 Android 开发者,如果你是新手,那么下面的内容可以帮助你找到学习的线路;如果你是老手,这篇文章列出的内容也可以帮助你查漏补缺。如果各位有什么其他的建议,欢迎留言交流
下面记录了我 2020 年的读书单,所记录的,都是已经读完了的,技术书籍由于很难定义读完,所以不在此列。
我比较喜欢读历史相关的书,其中 汴京之围 这本书读起来非常难受,弱国无外交,真的是写实;坏小孩 书如其名,个人感觉是要比电视剧好很多;重来 2 和 重来 3 跟工作相关,讲的是远程工作和工作方法,跟 2020 年居家办公的大趋势一致,白领程序员推荐看一下;我的最后一本减肥书 则比较系统和专业地讲了一下减肥相关的知识,对于在减肥的我来说很有用;最后 镖人 也算是国漫经典了,等出完了之后我一定要买一套实体书典藏(巨人也是)
2020 读书不多,2021 要加大这方面的投入,读 + 记录 + 总结 ,读书笔记后续都会补上
本文是 Systrace 系列文章的第十二篇,主要是对 Systrace 中的 CPU 信息区域(Kernel)进行简单介绍,简单介绍了如何在 Systrace 中查看 Kernel 模块输出的 CPU 相关的信息,了解 CPU 频率、调度、锁频、锁核相关的信息
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
本文是 Systrace 系列文章的第十一篇,主要是对 Systrace 中的 Triple Buffer 进行简单介绍,简单介绍了如何在 Systrace 中判断卡顿情况的发生,进行初步的定位和分析,以及介绍 Triple Buffer 的引入对性能的影响
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
本文是 Systrace 系列文章的第十篇,主要是对 Systrace 中的 Binder 和锁信息进行简单介绍,简单介绍了 Binder 的情况,介绍了 Systrace 中 Binder 通信的表现形式,以及 Binder 信息查看,SystemServer 锁竞争分析等
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
本博客内容主要集中在 Android 开发和优化相关的话题,包括一些性能工具的使用、Android App 优化知识、Android Framework 知识讲解,性能理论知识讲解等,这里整理了一份目录供大家参考,大家可以挑感兴趣的部分来看。这里不仅仅包含博客中的内容,一些我在 知乎 或者已停止运营的 The Performance 社群中的历史回答也会放到这里,不过这个目录里面放的都是我原创的博客,另外还收集了一些优秀文章,我也会不定期更新 Android 性能优化必知必会。
文章索引在前,工具、App 和内容项目集中在后面的个人项目。新增:AIW 开源介绍 · AIW GitHub 仓库。
本文是 Systrace 系列文章的第七篇,主要是是介绍 Android 中的 Vsync 机制。文章会从 Systrace 的角度来看 Android 系统如何基于 Vsync 每一帧的展示。Vsync 是 Systrace 中一个非常关键的机制,虽然我们在操作手机的时候看不见,摸不着,但是在 Systrace 中我们可以看到,Android 系统在 Vsync 信号的指引下,有条不紊地进行者每一帧的渲染、合成操作,使我们可以享受稳定帧率的画面。
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些
本文参考了目前大部分 Android 应用启动优化的方案,将大家的方案做一个汇总,如果你有这方面的需求,只需要对照这篇文章,看看其他人的方案,查漏补缺。很多方案是要根据具体的业务去做优化的,所以这里也没有对每一种方案进行详细的介绍,要用到哪一个方案的时候,可以具体去网上查找对应方案的具体实现方法,这里只是做一个汇总
另外我还加上了部分系统厂商所做的启动相关的优化,不过只写了一些我知道的,还有一些厂商有黑科技,就不在这里的讨论范围了。知道厂商做的事情,可能也会帮助到你,比如联系厂商做白名单、接入厂商 SDK 等
本文是 Systrace 系列文章的第九篇,主要是是介绍 Android App 中的 MainThread 和 RenderThread,也就是大家熟悉的主线程和渲染线程。文章会从 Systrace 的角度来看 MainThread 和 RenderThread 的工作流程,以及涉及到的相关知识:卡顿、软件渲染、掉帧计算等
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些
本文是 Systrace 系列文章的第六篇,主要是对 Systrace 中的 Input 进行简单介绍,介绍其 Input 的流程; Systrace 中 Input 信息的体现 ,以及如何结合 Input 信息,分析与 Input 相关的问题
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
这篇文章记录的是 2019 年遇到的后台动画问题:应用界面不可见了,进程里却仍有动画工作在执行。但是当用户知道一个 App 退到后台之后还在持续做无效的动画,而这个动画完全是无意义的,而且用户还不知道他在做动画,消耗用户那可怜的电量的时候,轻则被多任务杀掉,禁止后台运行,重则直接卸载。
这个问题容易被忽略。当时我使用 Systrace ,在多开应用后退回桌面,左右滑动并抓取 Systrace ,发现部分已离开的应用仍在频繁执行动画回调。复查时应固定操作和应用版本,并记录界面可见性,不能把“打开很多应用”当成必要或充分条件。
这里讨论的是界面已不可见、业务也不再需要,却仍持续推进的动画。它会增加不必要的工作;但进程还活着不等于能无限制使用 CPU,现代系统还可能冻结 cached 进程。往 Choreographer 提交动画回调的入口很多,最终要结合具体调用栈、播放状态和库版本定位,不能仅凭一个 animation slice 判定原因
本文介绍了 App 开发者不经常接触到但是在 Android Framework 渲染链路中非常重要的一个类 Choreographer。包括 Choreographer 的引入背景、Choreographer 的简介、部分源码解析、Choreographer 与 MessageQueue、Choreographer 和 APM,以及手机厂商基于 Choreographer 的一些优化思路
Choreographer 让动画、部分输入处理和 View 更新围绕显示时序协调执行。它在有待处理工作时请求帧回调,而不是每个物理刷新周期都无条件唤醒 App。2019 年常见的 60Hz 屏幕刷新间隔约为 16.67ms;90Hz、120Hz 分别约为 11.11ms、8.33ms,现代设备还可能动态切换刷新率。回调及时不等于画面已经呈现,后续还涉及 RenderThread、GPU 和合成显示链路。了解这套流程,也有助于理解 Message、Handler、Looper、MessageQueue、Measure、Layout 和 Draw。
在Android 中的卡顿丢帧原因概述 - 系统篇 这篇文章中, 实际案例这里我们有列举一些由于系统低内存导致的卡顿, 由于 Android 低内存对整机性能影响比较大, 所以单独写一篇文章, 来概述系统低内存对整机性能的影响 .
随着 Android 系统版本的更迭, 以及 App 的代码膨胀, Android 系统对内存的需求越来越大, 在写作当年的 2019 年,市面上还存在着大量 4GB 内存及以下的机器, 这部分用户就很容易遇到整机低内存的情况, 尤其是在系统大版本更新、同时运行的应用和服务增多的情况下 .
Android 内存压力可能导致性能问题, 具体表现就是响应慢和卡顿 . 比如启动一个应用要花比平时更长的时间 ; 滑动列表会掉更多帧 ; 后台的进程减少导致冷启动变多 ; 额外回收和重启工作也可能增加功耗,但发热本身不能证明低内存, 下面我会概述发生这些性能问题的原因 . Debug 的方法, 以及可能的优化措施 .
写这篇文章的契机是因为一个实际遇到的问题, 这个问题其实不难, 不过在分析了这个问题然后写日记的时候, 我突然觉得这个问题分析的过程有必要记录一下, 分享给大家 . 分析过程中有用到一些工具, 一些方法, 也从另外一个聪明的小伙伴梅明那里学到了一些分析技巧和工具的使用技巧 .
这篇文章中分析过程包括我之前在Android 中的卡顿丢帧原因概述 - 方法论 里面提到的一些工具, 包括 : 复现视频 \ Event Log \ Android Studio 源码和 App Debug \ Android Studio Profile \ Systrace \ Dumpsys \ PS 等 . 大多数工具大家都在开发过程中使用过, 这次分析正是使用了这些工具相互配合, 最终找到的问题的原因.
大家看下来可能会觉得, 这么简单一个问题还需要写一篇文章 ? 我写这篇文章的目的一是为了记录给自己, 二是觉得分析过程比较有普遍性, 包括分析思路和工具的使用, 如果可以帮助到大家, 那么最好不过了, 如果你也有好的思路或者独家调试技巧, 欢迎大家扫描关于我 里面的讨论群二维码加入群聊, 共同进步!
技术复核 · 2026-10-13。 保留 2019 年原图、线程列表与作者观点。技术核对基线为 AOSP
android-9.0.0_r1、android-16.0.0_r1;补充 API 31 帧时序与 DataStore 1.2.1 等现代入口。截图不是当前应用版本的测试结果,本次未做原设备或完整 Trace 复现。
在Android 中的卡顿丢帧原因概述 - 系统篇 这篇文章中我们列举了系统自身原因导致的手机卡顿问题, 这一篇文章我们主要列举一些由于 App 自身原因导致的卡顿问题. 各位用户在使用 App 的时候, 如果遇见卡顿现象, 先别第一时间骂手机厂商优化烂, 先想想是不是这个 App 自己的问题.
手机厂商和 App 团队会使用 Matrix 或自有方案收集线索,系统权限可增加可见信息,但数据范围仍取决于构建、采集配置和平台支持。
平均 FPS 不能单独代表流畅度。相同的 55 FPS 可以有不同的帧间隔和停顿分布;分析时需要目标节奏、实际呈现和输入响应,不能把 60→55 直接当作具体掉帧原因。本系列四篇如下:
技术复核 · 2026-10-13。 本文案例与截图来自 2019 年。此次按 Android 8.1/9/16 的相关源码、Linux v6.6 文档及现行 Android 文档核查,保留原始图片和作者经验;修正将长 slice、核号、内存回收或输入节奏直接等同根因的结论。没有重新运行原设备或回放完整 Trace,缺少的现场条件不作补造。
在应用篇中,我们列举了应用侧的卡顿问题。这一篇沿系统服务、显示、调度和内存路径整理案例。各设备的硬件、内核与厂商实现不同,定位时应保留系统版本和具体配置。
手机厂商和 App 开发者通常会通过优化组、Matrix 或自有监控方案收集线索。系统权限有助于获取更多数据,但采集范围仍受构建类型、内核配置和数据源开关影响。
流畅度不能仅等同于平均 FPS。60 Hz 下的一秒平均 55 FPS,无法说明延迟集中在哪几帧,也不能直接代表所有人的感知;应检查目标节奏、实际呈现间隔和输入响应。静止界面不需要每个刷新周期提交新内容。本系列四篇如下:
技术复核 · 2026-10-13。 本文保留 2019 年厂商优化组的工作经验与当时的行业观点。技术部分补充 Android 12(API 31)FrameTimeline、JankStats 与 Macrobenchmark 的适用边界;Looper 日志语义按 AOSP
android-9.0.0_r1/android-16.0.0_r1核对,Matrix 功能以 v2.1.0 文档为版本示例。本文未进行新的设备测量。
Android 手机使用中的卡顿问题,手机厂商和 App 开发商都会重视,内部一般会有基础组或者优化组负责分析和优化。
第三方工具如腾讯 Matrix 可以提供应用侧性能线索。厂商也会有自己的监控方案,借助系统源码和相应调试权限获取更深层数据;实际可见范围仍取决于系统版本、内核配置、构建类型和采集开关。
流畅度不能只用一秒内的平均 FPS 表示。相同的平均 55 FPS,可能包含一次明显停顿,也可能是较均匀的帧间隔,体验并不相同。要结合目标更新节奏、实际呈现间隔和输入响应看问题。60/90/120 Hz 的刷新间隔分别约为 16.67/11.11/8.33 ms,但它们不是所有线程合计的固定 CPU 时间预算;静止界面也不需要每个刷新周期都提交新内容。
引起卡顿的原因可能来自 App、系统、内核或显示链路。本系列分为四篇:
技术复核 · 2026-10-13。 本文保留 2019 年四种启动模式的操作记录,按 AOSP
android-9.0.0_r1、android-16.0.0_r1核对任务选择、affinity 与最近任务行为,并补充 Android 12(API 31)的 singleInstancePerTask。旧记录未注明设备完整版本,本次没有真机重跑,不能当作当前系统的逐步实测。
Android 中的 Activity 有几种重要的启动模式:standard、singleTop、singleTask、singleInstance。网上讲这些模式的文章不少,我这里写了个 Demo,想从任务中的 Activity 排列给大家看它们的区别;较新的 singleInstancePerTask 放在后面补充。
普通任务内导航通常后进先出。下方 A -> B 表示操作顺序;“栈内容”按顶部在前列出实际排列。留意每一步之后的变化,边操作边对照会好理解一些。重复发起启动不一定增加实例。Task 是系统管理的任务,不等于进程,也不等于最近任务列表中的一张卡片。
Demo 我也放到了 GitHub:AndroidLunchModeTest。本次核对的快照为 eaa1f987e332e0f85187a911ad9ae01cd20fff05。工程 compile/target SDK 29、min SDK 26;源码包名为 com.example.lunchmodetest,与下方保留的旧日志 com.example.launchmodetest 不同。
运行前需要按每个案例核对所有跳转目标:快照中 MainActivity.startSingleTopActivity 实际跳到 SingleTaskActivity,StandardActivity 默认跳到 SingleInstanceWithAffinityActivity,仅改一个目标无法自动跑完全部案例。类名 WithAffinity 表示旧命名,实际 manifest 配置为空 affinity;SingleTopWithAffinityActivity 甚至未声明 singleTop,不能凭类名判断模式。本次只核查代码,没有改动或编译这个示例工程。
下面先按同一用户、普通前台 Activity 发起、无额外 Intent flags 的条件解释。若把旧工程升级到 target SDK 31+,还需为带 intent-filter 的组件显式配置 android:exported,其中 Launcher 入口设为 true。
2026-10-13 技术更新:本文保留 2019 年起积累的旧 Systrace 截图,其中也有后补的案例。颜色与快捷键属于 legacy UI;Linux 状态说明参照 v6.6 文档,现代入口核对到 Perfetto UI v58.3(11fbaed83)。原图里的 Self Time、唤醒及调度状态注释有几处不准确,已在相邻正文说明;截图不等于本次设备实测。
本文是 Systrace 系列文章的第二篇,主要是讲解一些分析 Systrace 的预备知识, 有了这些预备知识, 分析 Systrace 才会事半功倍, 更快也更有效率地找到问题点.
本文介绍了如何查看 Systrace 中的线程状态, 如何对线程的唤醒信息进行分析, 如何解读信息区的数据, 以及介绍了常用的快捷键. 通过本篇文章的学习, 相信你可以掌握进程和线程相关的一些信息, 也知道如何查看复杂的 Systrace 中包含的关键信息
2026-10-13 技术更新:保留原有历史截图和代码。文中代码片段已对照 AOSP
android-10.0.0_r1,现代差异以android-16.0.0_r1为例;这不表示原截图运行的就是这些版本,原始 Trace、ROM 和构建信息并未附上。窗口动画归属、StartingWindow 与线程相互影响的旧说法已在下文修正。
本文是 Systrace 系列文章的第四篇,主要是对 SystemServer 进行简单介绍,介绍了 SystemServer 中几个比较重要的线程,由于 Input 和 Binder 比较重要,所以单独拿出来讲,在这里就没有再涉及到。
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
2026-10-13 技术更新:原文发表于 2019 年,旧 Systrace HTML 和脚本步骤保留作历史参考。现代抓取示例以 Android 11 / API 30+ 为起点;应用 Trace API、权限和数据源的版本边界另行注明。本文同时区分设备端
atrace、主机端systrace.py与perfetto,参数不能混用。
本文是 Systrace 系列文章的第一篇,主要是对 Systrace 进行简单介绍,介绍其简单使用方法;如何去看 Systrace;如何结合其他工具对 Systrace 中的现象进行分析。
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
2026-10-13 技术更新:本文原发表于 2019 年,以 60 Hz 设备解释帧节奏。60 FPS 不是所有 Android 设备的固定标准;旧文中的统一 16.67 ms 预算、帧率不匹配及功耗结论已在下文修正,并补充 Android 11 / API 30、Android 12 / API 31 起的适配与分析入口。
本文是 Systrace 系列文章的第三篇,解释一下为何大家总是强调 60 fps。这里的 FPS 指应用画面的帧率,Hz 指屏幕刷新率,两者统计的对象不同,可以参考这篇文章:新的流畅体验,90Hz 漫谈
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 的运行,从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
本文先分清帧率与刷新率,再讨论帧节奏、功耗和响应延迟。到了 90 Hz、120 Hz 设备上,仍需要让内容更新与显示时序配合,但不再把 60 FPS 或 16.67 ms 当成统一标准。
2026-10-13 技术更新:本页原标注日期为 2019 年,保留了更早教程的更新记录。旧 Systrace 工具流程已过时;历史截图、源码和实验按各篇注明的 Android 版本阅读,不能直接当作当前系统实现。新抓取与分析流程从下方 Perfetto 系列开始。
随着 Systrace 的功能越来越完善,加上 Android 版本的更迭,之前写的 Systrace 系列教程已经有点过时;另外随着自己技能的完善,从 Systrace 里挖掘了更多的信息,对解决各种性能问题很有帮助。这些技能我需要记录下来,增强自己的总结和归纳的能力,如果能帮助到看文章的人,也是极好的
本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。
2018 年初写了一篇<2017 年度最推荐-给辛勤工作的自己一点奖励>, 最近有人问我今年是否会有 2018 年的年度推荐,我想了想,2018 年虽然不景气,但是还是有一些好东西可以推荐给大家,于是便有了这一篇文章。
跟 2017年一样,我会把 2018 年里面我觉得体验很棒或者对工作生活很有帮助的东西推荐给大家,或许 2019 你会需要他们。推荐的内容包含了 App、硬件、书籍、博客、专栏等,希望能帮助到看到这篇文章的你
历史推荐(2026-10 核查):本文记录 2018 年的使用体验,书目、评分、价格、课程海报和购买建议均保留当年语境。软件支持范围与会员权益的变化在下文补充;旧二维码不作为当前报名入口。
我们经常说 iOS 整机体验要比 Android 好,这里有第三方软件的功劳(iOS 版本质量要高于 Android 版本质量),当然也归功于苹果对 iOS 的封闭系统的管控。应用想上 App Store,就得先过审核,不合规就给你打回来。
今天我们要说的是系统在应用内容就绪前提供的启动过渡画面。Android 常称之为 StartingWindow,iOS 的对应概念是 Launch Screen;两者不能等同于应用启动后自己展示的广告 Activity 或业务首页。
我原先把 iOS 启动画面说成“必须是一张图片”,这里说错了:Xcode 6 发布说明明确记录 iOS 8 起支持 XIB/Storyboard 启动画面。它们帮助系统尽早给出反馈,但“点击后零延迟”不是可保证的时序。Android 的旧实现允许通过主题影响启动预览,也有禁用预览或透明窗口的路径;具体规则要看系统版本。
这篇文章记录了 Android 性能优化所必须掌握的知识(主要是对应的优秀文章、公众号、博客、技术团队等),涵盖性能优化相关的方方面面。本文会持续更新,欢迎各位自荐或者推荐。
2017 不知不觉已经走过,博客已经许久没有更新了,一个原因是越来越觉得自己的学识浅薄,怕写了技术误了大家,另一个原因是自己太懒了。鉴于上面两个原因,我决定此博客的更新,不再非要更新技术文章,一些我觉得有意义的事情、思考等,也会更新上来。一方面自己做个记录,如果能顺带给读者带来一点帮助,那自然是最好的(虽然没几个读者…)
2017 既然才刚刚过去,我觉得有必要把 2017 年里面我觉得体验很棒或者对工作生活很有帮助的东西推荐给大家,或许 2018 你会需要他们。推荐的内容包含了 App、硬件、书籍、器材等,需要说明的是,这些东西是我觉得 2017 年给我带来很大帮助的,适合我不一定适合你。话不多说,直接上内容吧!
一转眼就 2017 年了,算起来自己已经工作了快四年了,09年到威海上学,12年去上海实习,13年毕业后还是去了上海,14年进了珠海魅族,直到现在。
这博客从我毕业开始写东西,写写删删,也算是记录了一些东西,自己的工作内容也从 App 开发换到了系统 App 开发,再换到系统开发,也算是走了一圈,一些路程,记录下来,几年后再看看,怀念一下也是不错的。
这篇文章我记录了自己的博客、自己的工作、自己的工作内容、自己的工作习惯、还有对 2017 年的期望,有迷茫,也有奋斗。
17年已经过了 30% 了,希望还不算晚。
Android 官方在 2016 年 3 月更新了 Bottom navigation 设计规范,所谓设计规范就是告诉开发者和设计师要如何去设计和使用某一个组件。不过这次 Bottom navigation 的发布,让许多人大跌眼镜,毕竟 Bottom navigation 这样的组件,在之前的 MD 设计语言中可是只字未提,当时 Android 与 iOS 常见的导航布局也有差异:iOS 应用常用底部标签栏,Android 的旧指南则建议避免这种布局。这是设计建议的变迁,不是两个平台的能力限制,也不是所有 iOS 应用都必须使用底栏。
本文是 Android Bottom navigation 的第二篇文章,主要介绍样式、行为与规格。