第1章 AMS与WMS基础与性能模型:服务职责、通信链路、性能影响因子

1.1 服务职责全景

Android 系统中,AMS(ActivityManagerService) 与 WMS(WindowManagerService) 是两大核心系统服务,分别掌管应用生命周期与窗口管理。理解它们的职责边界是性能调优的第一步。

维度 AMS WMS
核心职能 Activity 栈管理、进程调度、Intent 解析、权限校验 窗口层级管理、输入事件分发、屏幕旋转、壁纸管理
关键数据结构 ActivityStack、TaskRecord、ProcessRecord WindowState、WindowToken、DisplayContent
IPC 通道 IActivityManager(Binder) IWindowManager(Binder)
性能敏感路径 startActivity、bindService、进程杀/拉 relayoutWindow、setWindowLayout、input dispatch
线程模型 ActivityManagerThread(主线程)+ 多个 Worker WindowManagerThread(主线程)+ 动画线程
调优认知起点: AMS 的瓶颈通常出现在 栈遍历 和 进程 OOM 调整 场景;WMS 的瓶颈集中在 窗口重新布局 和 输入事件分发链路 上。调优前必须能区分两类延迟来源。

1.2 通信链路分析

AMS 与 WMS 各自通过独立 Binder 通道与应用进程通信,同时两者之间通过内部回调互相协作。下面从链路层面拆解一次典型 Activity 启动过程中的关键通信节点。

1.2.1 链路全景

  1. 应用进程发起 Intent → 通过 Binder 调用 AMS.startActivity()
  2. AMS 解析栈与进程状态 → 若目标进程未启动,通过 Zygote 孵化新进程
  3. AMS 通知 WMS 准备窗口 → 调用 WMS.prepareAppTransition() + setAppVisibility()
  4. WMS 计算窗口层级与动画 → 向 SurfaceFlinger 提交事务
  5. 应用进程通过 relayoutWindow() 获取 Surface → 开始渲染第一帧
  6. WMS 回调 AMS.reportActivityVisible() → AMS 完成启动时序
链路关键时延点: 第3步 AMS→WMS 跨服务调用是串行阻塞的;第5步 relayoutWindow() 涉及 Buffer 分配与 Layer 创建,是 WMS 侧 CPU 峰值消耗点。

1.2.2 Binder 通信开销实测经验

使用 dumpsys binder 可以查看 AMS/WMS 对应 Binder 通道的调用频率与耗时:

adb shell dumpsys binder --stats | grep -E "android.app.IActivityManager|android.view.IWindowManager"

典型输出片段中,procStartTime 与 replySize 可直接反映通信负载。若单次调用 > 5ms 且频率 > 200次/秒,说明 Binder 线程池已接近饱和。

1.3 性能影响因子矩阵

从系统资源视角,将 AMS 与 WMS 的性能影响因子归纳为以下四类:

影响因子 AMS 敏感度 WMS 敏感度 典型症状
Binder 线程池耗尽 高 高 Activity 启动卡顿、窗口无响应
主线程锁竞争(AMS/WMS 内部锁) 极高 极高 串行排队导致 ANR
SurfaceFlinger 事务积压 低 高 窗口创建/旋转掉帧
进程 OOM 优先级调整 高 低 后台进程频繁被杀/重启
窗口层级深度 低 高 输入事件分发延迟
ContentProvider 冷启动 中 低 首次启动速度慢
常见误判: 开发者经常将 WMS 侧的 窗口布局延迟 误判为 GPU 渲染问题。区分方法:抓取 systrace 中 WMS.relayoutWindow 与 SurfaceFlinger 的间隔,若前者 > 4ms 而后者正常,则瓶颈在 WMS 而非 GPU。

1.4 AMS 与 WMS 性能模型

建立量化性能模型有助于定位调优优先级。将 AMS 与 WMS 的请求处理抽象为三阶段流水线:

  • 入队阶段(Enqueue):Binder 从应用进程接收调用,放入服务端工作队列。耗时取决于 Binder 线程池空闲数。
  • 处理阶段(Process):服务主线程或 Worker 执行核心逻辑(栈操作/窗口计算)。耗时取决于内部锁持有时间与数据结构大小。
  • 回写阶段(Reply):将结果序列化写回 Binder 缓冲区。耗时与 reply 数据量成正比。
模型公式(经验参考):
Ttotal = Tenqueue + Tprocess + Treply
当 Tenqueue / Ttotal > 0.4 时,优先扩容 Binder 线程池(maxThreads 从 16 调至 24);
当 Tprocess / Ttotal > 0.5 时,聚焦代码路径优化或锁拆分。

1.5 系统架构与通信链路图

AMS 与 WMS 系统架构与通信链路 AMS 与 WMS 系统架构与通信链路 AMS (ActivityManagerService) WMS (WindowManagerService) Activity 栈管理 进程调度 (OOM) Intent 解析 权限校验 窗口层级计算 输入事件分发 动画 / 转场 Surface 管理 应用进程 (App) SurfaceFlinger 内部回调 startActivity() relayoutWindow() setLayer / transaction dequeueBuffer 图例说明 蓝色/紫色节点 = AMS 核心模块;红色/橙色节点 = WMS 核心模块 绿色节点 = 应用进程;青色节点 = SurfaceFlinger 虚线箭头 = Binder IPC 调用;实线箭头 = 内部回调 / 事务提交

1.6 调优切入路径

基于上述性能模型与影响因子矩阵,给出三条可立即落地的调优切入路径:

  1. Binder 线程池扩容 —— 在 system_server 启动参数中调整 -Dandroid.binder.maxThreads=24,适用于多并发 Activity 启动场景。
  2. WMS 锁拆分 —— 针对 WindowManagerService.java 中的 mWindowMap 锁,将窗口遍历与布局计算拆分为读写锁,减少主线程阻塞。
  3. AMS 栈剪枝 —— 对于超过 8 层的 Activity 栈,启用 FLAG_ACTIVITY_CLEAR_TOP 或主动收缩栈深度,降低 startActivity 时的栈遍历耗时。
快速验证命令:
查看当前 AMS/WMS Binder 调用统计:
adb shell dumpsys activity processes
adb shell dumpsys window --layout
关注 mBinderTransactionCount 与 mRelayoutCount 两个计数器,若超过 5000次/分钟 则需要介入优化。

1.7 常见错误与避坑

错误认知 实际原理 后果
「ANR 都是应用主线程阻塞」 AMS 主线程持有锁时,应用 Binder 调用也会排队阻塞,间接导致应用 ANR 误抓应用侧堆栈,忽略 system_server 锁竞争
「窗口卡顿就是 GPU 丢帧」 WMS relayoutWindow 耗时 > 8ms 会导致应用无法及时获取有效 Surface,即使 GPU 空闲也会掉帧 盲目优化 GPU 渲染,浪费精力
「后台进程越多越好」 AMS 维护的 ProcessRecord 越多,OOM 调整与栈遍历的线性开销越大,拖慢前台启动性能 启动速度随后台进程数增加而劣化
调优红线: 不要直接修改 ActivityManagerService.java 或 WindowManagerService.java 中的 synchronized 块作用域——错误的锁粒度调整可能引发死锁或 visibility 问题。建议先在 systrace 中锁定热点锁,再通过 ReentrantReadWriteLock 或 StampedLock 渐进替换。

1.8 本章小结

  • AMS 负责应用生命周期与进程调度,WMS 负责窗口层级与输入分发;两者的 Binder 通信链路是性能瓶颈的集中区域。
  • 性能影响因子包括 Binder 线程池、内部锁竞争、SurfaceFlinger 事务积压和进程 OOM 调整优先级。
  • 建立 Tenqueue + Tprocess + Treply 三阶段模型,可量化定位调优方向。
  • 三条切入路径:Binder 线程扩容、WMS 锁拆分、AMS 栈剪枝;使用 dumpsys 命令快速验证效果。