性能优化不能只靠本地 Profile。用户手里的设备千奇百怪:低端机、老旧系统、弱网环境、后台被杀。你只有在线上真实环境中采集数据,才能发现真正的问题。
这篇会讲如何搭建 Android 性能监控体系:从指标选择、本地采集、上报策略,到最终形成 APM 闭环。
一、APM 应该监控什么?
不是指标越多越好。初级阶段盯住这几个核心指标:
二、本地采集:关键指标怎么算?
2.1 启动时间
Application 启动:
class MyApp : Application() {
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
// 记录进程启动时间
ProcessStart.record()
}
override fun onCreate() {
super.onCreate()
// Application 初始化完成
ProcessStart.appOnCreateEnd()
}
}
Activity 首帧:
class MainActivity : AppCompatActivity() {
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
ProcessStart.firstFrame()
}
}
}
2.2 FPS 与卡顿
用 Choreographer 采集帧耗时:
Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback {
private var lastFrameTime = 0L
override fun doFrame(frameTimeNanos: Long) {
if (lastFrameTime != 0L) {
val diffMs = (frameTimeNanos - lastFrameTime) / 1_000_000
if (diffMs > 16.6f) {
recordJank(diffMs)
}
}
lastFrameTime = frameTimeNanos
Choreographer.getInstance().postFrameCallback(this)
}
})
2.3 内存
val runtime = Runtime.getRuntime()
val usedMem = (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024
val maxMem = runtime.maxMemory() / 1024 / 1024
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val memInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memInfo)
val availMem = memInfo.availMem / 1024 / 1024
2.4 网络请求耗时
用 OkHttp 拦截器统一采集:
class MetricsInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val start = SystemClock.elapsedRealtime()
val request = chain.request()
val response = chain.proceed(request)
val cost = SystemClock.elapsedRealtime() - start
NetworkReporter.report(
url = request.url.toString(),
code = response.code,
cost = cost
)
return response
}
}
三、埋点设计:少而精
3.1 事件埋点 vs 指标埋点
性能监控以指标埋点为主,事件埋点为辅。
3.2 采样策略
全量上报会拖垮 App 和后端。合理采样:
object Sampler {
fun shouldReport(event: String): Boolean {
return when (event) {
"app_launch" -> true // 启动全量
"fps" -> Random.nextFloat() < 0.1f // FPS 10% 采样
"network" -> Random.nextFloat() < 0.05f // 网络 5% 采样
else -> Random.nextFloat() < 0.01f
}
}
}
3.3 用户维度聚合
上报时带上:
设备型号、系统版本。
App 版本、渠道。
网络类型(WiFi/4G/5G)。
用户分桶 ID(用于 A/B 实验)。
这样可以在 APM 后台按维度下钻。
四、上报策略:离线缓存 + 批量上传
4.1 本地缓存
class MetricsCache(private val file: File) {
fun append(event: MetricEvent) {
file.appendText(Json.encodeToString(event) + "\n")
}
fun readAndClear(): List<MetricEvent> {
if (!file.exists()) return emptyList()
val lines = file.readLines()
file.delete()
return lines.map { Json.decodeFromString(it) }
}
}
4.2 批量上报
fun flushCache() {
val events = cache.readAndClear()
if (events.isEmpty()) return
viewModelScope.launch(Dispatchers.IO) {
try {
api.reportBatch(events)
} catch (e: Exception) {
// 失败则重新写回缓存
events.forEach { cache.append(it) }
}
}
}
触发时机:
App 切换到后台。
缓存达到一定条数(如 50 条)。
每 5 分钟一次。
用户手动退出。
五、从数据到行动:APM 闭环
采集数据只是第一步,更重要的是根据数据优化。
5.1 建立基线
先定义每个指标的 P50、P90、P99 基线:
5.2 告警与归因
APM 后台需要:
指标异常时自动告警(如 P99 启动时间环比上涨 20%)。
按版本、机型、地域下钻。
卡顿堆栈自动聚类,定位高频问题函数。
5.3 闭环流程
采集 → 上报 → 聚合 → 告警 → 定位 → 修复 → 验证 → 采集
没有闭环的 APM 只是数据 dashboard。
六、开源与商业方案
建议:先用商业方案跑通流程,再决定是否自研。
小结
性能监控框架是连接线上和研发的桥梁:
指标不在多,关键是启动、FPS、内存、网络、崩溃。
本地采集用 Choreographer、Runtime、OkHttp 拦截器。
上报要采样、批量、离线缓存。
APM 必须形成闭环:采集 → 告警 → 定位 → 修复 → 验证。
小型项目先用商业方案,大型项目再考虑自研。
下篇预告
下一篇《第 14 篇:Android 安全:反编译、加固、签名与数据保护》会讲 Android 安全:
APK 反编译有多容易。
代码混淆、VMP、加固的基本原理。
本地数据、密钥、通信的安全实践。
参考阅读
Android 官方 Profiling 文档
Firebase Performance Monitoring 文档
《Android 性能优化:权威指南》
上一篇文章:第 12 篇《Native 集成:JNI、NDK、C++ 与 Kotlin 的协作》