如何定义和监控 App 的关键性能指标(KPI)如启动时间、FPS、内存峰值?

解读

面试官问的是“定义+监控”,不是“优化”。
国内大厂(阿里、腾讯、字节、美团)的面试套路是:先让你给出“可落地、可灰度、可告警”的指标定义,再追问“线上全量监控怎么做、线下复现怎么做、异常样本怎么回捞”。
因此答案必须包含:

  1. 指标的业务定义(对齐产品/运营口径)与技术定义(对齐系统 Trace 点)。
  2. 线下实验室采集方案(用于复现与竞品对标)。
  3. 线上真实用户监控方案(RUM,支持分渠道、分机型、分系统版本、分 AB 实验)。
  4. 阈值与告警(P50/P90/P99 分位,同比/环比波动)。
  5. 国内合规与隐私(不采集 IMEI、MAC,只采 OAID/匿名 UUID,数据本地化存储)。

知识点

  1. 启动时间
    冷启动:Application.attachBaseContext → FirstFrame(DecorView 绘制完成)。
    热启动:Activity.onRestart → FirstFrame。
    完全可交互(TTI):首帧完成后主线程 1 s 内无阻塞任务。
  2. FPS
    系统 Choreographer 回调间隔 → 帧耗时 → 丢帧数(>16.67 ms 即一帧)。
    平滑度:掉帧率 = 丢帧数/总帧数;卡顿率 = 连续丢 3 帧以上次数。
  3. 内存峰值
    JavaHeap:Runtime.totalMemory – Runtime.freeMemory。
    NativeHeap:Debug.getNativeHeapSize。
    Graphics:EGL/GL 驱动统计,需 hook libgui.so。
    系统级:ActivityManager.getProcessMemoryInfo 的 totalPss。
  4. 合规采集
    国内统一用 MSA OAID 做设备匿名化;启动、内存、帧率数据走自定义采样(默认 5%,可云端配置)。
  5. 监控框架
    线下:Perfetto/Systrace + GPU 呈现模式分析 + AS Profiler。
    线上:字节 Booster、阿里 Sophix-RUM、腾讯 Matrix、美团 Hertz 均开源,可直接谈实现思路。

答案

一、指标定义

  1. 冷启动耗时(ms)
    起点:Application.attachBaseContext() 第一次被调用;
    终点:首帧 Choreographer 回调完成,同时 ViewTreeObserver 的 onDraw 回调已触发;
    采样:5% 用户,本地写环形内存缓冲区,满足采样率后随业务日志上报。
  2. FPS & 掉帧率
    自建 FrameMonitor 类,在主线程 postFrameCallback,记录两帧间隔;
    丢帧阈值:单帧 >16.67 ms;
    卡顿阈值:连续丢 3 帧;
    指标:平均帧率、掉帧率、卡顿次数/10 min。
  3. 内存峰值
    进程级别:每 1 s 读取 ActivityManager.getProcessMemoryInfo().totalPss,滑动窗口取最大值;
    Java 堆:Runtime.getRuntime().totalMemory – freeMemory;
    Native 堆:Debug.getNativeHeapAllocatedSize;
    上报时携带当前应用前后台状态、UI 可见页面,方便后台聚类。

二、线下实验室监控

  1. 使用 Google Perfetto 录制完整 trace,标记 Application 的 Start 与 FirstFrame 的自定义 slice,自动化脚本输出冷启动耗时;
  2. 打开“GPU 呈现模式分析”→“在屏幕上显示为条形图”,人工走查核心路径,确保无红色帧;
  3. 使用 AS Memory Profiler 执行强制 GC 后观察 Java 堆是否回到基线,确认无泄漏;
  4. 结果写入内部云测平台,与竞品横向对比,必须优于行业 P90 值(冷启动 <1.2 s,掉帧率 <1%)。

三、线上真实用户监控(RUM)

  1. 采集 SDK 以 AOP 方式插桩,无侵入:
    • 启动:在 Application.attachBaseContext 与 Activity.onCreate 末尾埋点;
    • 帧率:注册 Choreographer.FrameCallback;
    • 内存:后台线程定时采样。
  2. 采样策略:
    • 低端机(RAM<4G)采样率 10%,高端机 3%,灰度发布阶段可动态调整;
    • 单设备单日最多上报 200 条,防止流量浪费。
  3. 上报字段:
    匿名设备 ID(OAID)、系统版本、应用版本、渠道、AB 实验 ID、页面路由、前后台标志、电量等级。
  4. 后台聚合:
    • 按分钟级聚合 P50/P90/P99;
    • 同比昨日、环比上周,波动超过 10% 自动告警(飞书机器人 + 短信)。
  5. 异常回捞:
    触发阈值后,后台下发“回捞指令”,客户端在下次启动 30 s 内自动录制 10 s Perfetto trace,压缩后上传,供性能团队根因分析。

四、阈值与 OKR 对齐(2024 国内主流标准)
冷启动 P90 ≤1.5 s;热启动 P90 ≤500 ms;
掉帧率 P90 ≤1%;卡顿次数/10 min P90 ≤3;
Java 峰值内存 P90 ≤550 MB(1080P 手机);Native 峰值 ≤350 MB。

五、合规与隐私
不采集 IMEI、MAC、GPS;数据存储在阿里云华东节点;用户可“一键关闭性能诊断”开关,符合《个人信息保护法》与工信部 164 号文要求。

拓展思考

  1. 折叠屏与多窗口
    大屏展开后,Activity 重启但进程不杀,启动时间定义需区分“设备折叠状态”维度,避免误判。
  2. 5G 弱网
    启动阶段若触发网络模块初始化,需把“网络首包时间”从冷启动中拆解,防止把网络延迟算到启动耗时里。
  3. AI 加速模型加载
    TensorFlow Lite 的 GPU delegate 初始化可能耗时 200 ms,应放在启动后置任务,并通过启动框架按优先级串行调度,否则会把启动时间撑大。
  4. 隐私沙盒(Android 13 受限存储)
    采集 native 内存时若读取 /proc/self/smaps 被限制,需降级使用 Debug.getNativeHeapSize,同时后台对比两种口径差异,保证指标连续性。