Android 性能问题根因杂:同一份掉帧现象,可能是主线程 IO、GPU 过载、内存泄漏或网络请求占满线程池,根因天差地别,所以优化的第一步永远是定位而非改代码。本文按"先定位、再优化"组织:先用 vitals 看线上最差机型,再用 Profiler / Perfetto / GPU Inspector 本地抓帧,必要时用 Macrobenchmark 把修复固化成可回归数字;随后讲内存与网络两类具体优化,最后讲支撑刷新机制的 Choreographer。


一、线上先看 Android vitals:先锁定最差机型再动手

Android vitals 是 Google Play 控制台里的核心质量指标,用来衡量崩溃、ANR、启动时间、卡顿、电量和权限拒用。超过不良行为阈值会影响推荐和可见度。数据来自同意分享的真机,不是你实验室里的那几台。优化 vitals 要把线上聚合和本地复现连起来,而不是只看 Firebase 里的单条堆栈。Play 还会按 Android 版本和设备型号拆分,方便找机型问题。

三个容易踩的坑

  • 崩溃率和 ANR 是硬门槛。用户感知不良行为超过阈值会被标记,修复要按受影响用户数排序,而不是按条数。
  • 启动与卡顿看分位数。P90 比平均值更接近差体验,冷启动和完全绘制时间要分开看。
  • 电量与唤醒锁。后台唤醒、网络和定位会进 vitals,保活套路很容易把电量指标打爆。

什么时候用:应用上架或准备大版本时每周看 vitals 仪表盘。内测包和国内渠道包看不到同一套数据。优化前先锁定最差机型和版本,再用内部基准测试验证修复是否真的掉下去。


二、本地抓帧用 Perfetto 与 systrace:找到时间花在哪一帧

Perfetto 是 Android 官方的系统级跟踪工具,用来抓 CPU 调度、binder、图形、内存和你自己打的 trace 点。它比老 systrace 更能看长时间和多进程。捕获可以在设备上用 perfetto 命令,也可以在 Studio 的 CPU Profiler 里选 System Trace。分析时把主线程、RenderThread 和系统服务放在同一条时间轴上,卡顿是谁抢了 CPU 一目了然。线上还可以配合简化的 tracing 配置做短时抓取。

systrace 把系统与应用的时间片画成泳道:CPU 调度、SurfaceFlinger、Choreographer、Binder。抓一段操作后用 Perfetto 打开,看主线程是否在 vsync 间隔内完成、是否在等锁或 IO。它回答的是"这一帧时间花在哪",比日志更适合卡顿。Android Studio Profiler 里的 System Trace 就是同一套数据。抓取时长要覆盖完整手势,标签用 Trace.beginSection 标业务。关注 Alerts 里的掉帧和膨胀布局。CPU 跑满要看是渲染还是解码。和 BlockCanary 互补:一个给时间线,一个给堆栈。不要用它当日常监控,文件很大。先复现再抓,分析从主线程泳道开始。Systrace 是地图,优化仍要改布局、异步和过度绘制。

三个容易踩的坑

  • 配置要按问题裁剪(Perfetto)。查掉帧就开 sched、freq、binder 和 gfx,全开会把设备拖慢并把文件撑爆。
  • 看切片而不是看平均值。找到超时那一帧,看主线程是在 inflate、锁等待还是 binder 同步调用。
  • 抓 systrace 前先复现。覆盖完整手势,先复现再抓;文件很大,别当日常监控用。

什么时候用:启动慢、滑动掉帧、卡死或怀疑系统服务抢占时用 Perfetto。单纯 Java 热点可以先用采样 profiler。抓取前固定操作路径,捕获控制在几秒到十几秒,分析完再改代码验证。


三、开发机排障用 Studio Profiler:CPU、内存、网络一体化

Android Studio Profiler 把 CPU、内存、能耗和网络采样做到 IDE 里。CPU 记录器能看方法追踪和系统 Trace,内存能看堆转储和分配,网络能看连接时间线。它适合在开发机上快速验证一次滑动或一次请求有没有泄漏。和 Perfetto 相比,Studio Profiler 交互更方便但捕获窗口和细节有时不如独立工具。日常排障时它是第一站,深度帧分析再换更专业的捕获。

三个容易踩的坑

  • CPU 记录选对模式。Sample Java 看热点,System Trace 看线程调度和锁,Callstack 采样间隔会影响开销。
  • 内存要对比操作前后。看泄漏先做堆转储对比 Activity 是否被持有,不要只看曲线上涨就断定泄漏。
  • 能耗是估算。传感器和唤醒会进图,真机电量还得以 dumpsys batterystats 为准。

什么时候用:开发阶段查卡顿、泄漏和异常网络时打开 Profiler。线上聚合问题要靠崩溃平台和 vitals。开始前关掉无关插件,固定复现步骤,再点记录,避免把 IDE 本身的抖动算进应用。


四、GPU 瓶颈用 Android GPU Inspector:过绘制与带宽

Android GPU Inspector 用来剖析应用在 GPU 上的工作,包括帧捕获、DrawCall、纹理、管线和计数器。它适合查过绘制、过重着色器和带宽打满。和 CPU Profiler 互补:一边看主线程有没有及时提交,一边看 GPU 是否忙完一帧。AGI 可以连真机抓 Vulkan 或 OpenGL 帧,逐步看每个 pass。做自定义渲染、相机特效或游戏时,它比只看 FPS 数字更接近根因。

三个容易踩的坑

  • 先确认瓶颈在 GPU。CPU 等 GPU 和 GPU 等 CPU 是两种病,计数器里看 GPU 忙闲再动手。
  • 过绘制和带宽最常见。半透明层叠、全屏模糊和大纹理会把移动 GPU 拖死,先减层再谈算法。
  • 捕获要可复现。同一场景、同一分辨率,否则优化前后对不上。

什么时候用:掉帧伴随 GPU 占用高、发热或自定义 GL 绘制异常时打开 AGI。纯列表卡顿先查主线程绑定。分析前装好驱动与匹配的设备系统,捕获失败多半是版本不兼容而不是应用没问题。


五、给 PR 一个回归数字用 Macrobenchmark

Macrobenchmark 是 Jetpack 提供的端到端性能基准库,在独立测试进程里启动你的应用,测量启动、滚动和自定义关键路径。它和 Benchmark 微基准不同,微基准测函数,Macrobenchmark 测用户能感觉到的旅程。结果可以输出到系统 Trace,方便和 Perfetto 对着看。CI 里跑它要固定设备和编译模式,否则数字会飘。CompilationMode 还能验证 Baseline Profile 是否生效。

三个容易踩的坑

  • 测的是独立进程里的真实启动。不要在被测应用进程里跑,否则测到的是热乎乎的 JIT 状态。
  • 用 FrameTiming 和 StartupTiming 这类 metric。滚动要配合 RecyclerView 动作,启动要分冷热温。
  • Baseline Profile 要一起验证。编译模式选 Partial 才能看出配置文件有没有缩短首次帧。

什么时候用:优化启动或列表流畅度、要给 PR 一个可回归数字时用 Macrobenchmark。单函数分配次数用微基准。接入时先写一条冷启动用例跑通,再扩到滚动和复杂页面。


六、内存优化:先修泄漏再谈图片格式

Android 内存优化先分泄漏与峰值。泄漏常见于静态 Context、匿名内部类、未反注册监听、WebView、单例缓存 Bitmap。LeakCanary 抓引用链,MAT 看 dominator。峰值靠 Bitmap 采样、inBitmap 复用、大图不进内存缓存。

onTrimMemory 时释放缓存。避免在热路径分配短命对象。RecyclerView 里 bind 不 new 监听器。进程级看 dumpsys meminfo 与 RSS/PSS。Native 泄漏要配合 AddressSanitizer 或 jemalloc 剖析。

不要一上来加大 heap。先修泄漏再谈图片格式(RGB_565 vs HARDWARE)。多进程会让 PSS 翻倍。上线用采样监控 OOM 率,而不是只看测试机。

什么时候用:出现 OOM、内存曲线只涨不跌、或后台被系统杀进程时做内存优化。进程级看 dumpsys meminfo 与 RSS/PSS,Native 泄漏要配合 AddressSanitizer 或 jemalloc。热路径避免分配短命对象,RecyclerView 里 bind 不 new 监听器,onTrimMemory 时释放缓存。


七、网络优化:减少请求数与传输量

网络优化(网络连接对用户的影响:流量、电量、用户等待)可在 Android Studio 下方 logcat 旁边的 Network Monitor 工具检测。

四个关键做法

  • API 频次设计。在 App 与 Server 之间考虑请求频次和资源状态,用较少的请求完成业务与界面展示。
  • Gzip 压缩。压缩 request 和 response,减少传输数据量,从而减少流量消耗。
  • 图片尺寸协商。获取图片时告知服务器需要的宽高,让服务器返回合适尺寸,避免浪费。
  • 网络缓存。适当的缓存既让应用"看起来更快",也避免不必要的流量消耗。

什么时候用:界面加载慢、流量消耗高、弱网下体验差时做网络优化。用 Network Monitor 检测连接时间线,重点看请求频次与传输体积,配合缓存让应用"看起来更快"。


八、看懂刷新节拍用 Choreographer:一帧只做一次布局遍历

Choreographer 是 Android 主线程与屏幕刷新节拍的同步器。VSYNC 到达后,它依次执行 INPUT、ANIMATION、TRAVERSAL 三类回调,分别对应输入分发、动画计算与 View 布局绘制。一帧 16.6ms 内走不完,下一帧就会掉帧。

理解它对性能排查很有用:postFrameCallback 可以监控帧间隔;过重的布局、主线程 IO、过频的 requestLayout 都会把 TRAVERSAL 拖长。动画应挂在 Choreographer 而不是自己开 Handler 死循环。从 Android 12 起还能通过 FrameTimeline 看到 vsyncId,帮助对齐 GPU 渲染与主线程负载。优化时先保证一帧只做一次布局遍历。

什么时候用:排查掉帧、帧间隔抖动、动画卡顿时看 Choreographer。用 postFrameCallback 监控帧间隔,优化时先保证一帧只做一次布局遍历。


附:工具 → 查什么 → 什么时候用 对照表

工具 查什么 什么时候用
Android vitals 崩溃率、ANR、启动/卡顿分位数、电量(线上真机) 上架或大版本前每周看,先锁定最差机型与版本
Perfetto / systrace 主线程、RenderThread、系统服务时间轴,掉帧落在哪一帧 启动慢、滑动掉帧、卡死、怀疑系统服务抢占;先复现再抓
Studio Profiler CPU 热点、堆转储与分配、网络时间线(IDE 一体化) 开发阶段快速验证卡顿、泄漏、异常网络,日常第一站
Android GPU Inspector DrawCall、过绘制、着色器、带宽、GPU 计数器 掉帧伴随 GPU 占用高、发热、自定义 GL 绘制异常
Macrobenchmark 启动/滚动/关键路径的可回归数字,Baseline Profile 是否生效 给 PR 一个回归数字;单函数分配用微基准
内存工具(LeakCanary / MAT / dumpsys) 泄漏引用链、dominator、RSS/PSS OOM、曲线只涨不跌、后台被杀时
Network Monitor 请求频次、连接时间线、传输体积 界面加载慢、流量高、弱网体验差时
Choreographer 帧间隔、VSYNC 回调、TRAVERSAL 是否被拖长 掉帧、帧间隔抖动、动画卡顿