本文为现代化 Android 开发系列文章第七篇。
完整目录为:
- 现代化 Android 开发:基础架构
- 现代化 Android 开发:数据类
- 现代化 Android 开发:逻辑层
- 现代化 Android 开发:组件化与模块化的抉择
- 现代化 Android 开发:多 Activity 多 Page 的 UI 架构
- 现代化 Android 开发:Jetpack Compose 最佳实践
- 现代化 Android 开发:性能监控(本文)
性能优化是开发永远绕不过的话题,也是通往高手的必经之路。但性能优化的前提是搭建了完善的性能监控体系,大公司都会投入人力建设完善的 APM 监控体系,而小公司则更多的只能使用大公司提供的平台与 SDK,甚至由于业务压力,往往也没有时间去搞什么性能优化。所以说这方面的成长,那得倒退几年,在大公司才有机会得到锻炼。而现在,该有的 APM 系统都有了,已经是维护为主了。对外的 SDK 与平台都在想方设法收点费了,小公司能够看数据分析的地方就更少了。
如果是学习的话,那么极客时间上张绍文大佬的《Android开发高手课》就是非常推荐的学习资源了,崩溃、内存、IO、存储、网络、启动、包体积、UI等方方面面都有讲得很深。而且大佬是非常注重线上监控的,力求做到问题早暴露、早处理。
作为业务开发的我,当然不是讨论各个底层的实现,而是利用各种库和工具来完成自己的监控目的,所以本文主要讨论的业务层可以使用哪些工具。
上报
各大平台提供大而全的 SDK,则是采集-上报-分析一条龙的都承包了,对于使用端而言则是几句代码的事了,所以它点费也是理所应当,不过,小公司,非必要,给钱是不可能给钱的了。所以我在 emo 中开发了通用的上报库 report,封装了立即上报、批次上报等行为逻辑,后端可以使用 Prometheus,这就是把监控也作为业务数据上报的一部分。而因为 report 是一个通用的上报库,使用者需要自定义数据协议,所以 emo 之前规划的一个发展就是定制各种监控的数据协议,和后端提供配套的 docker,不过也只是有心而无力,没这个排期。
Crash
Crash 、ANR、OOM 应该是最受关注的监控对象,java 层的 crash 好捕捉,难的是 native 层的异常,难以捕捉,而且可能捕捉不到,所以往往为了获取详细的 crash 信息,大家都可能会同时接入几个 SDK 去监控。目前比较通用的可能还是 Bugly,毕竟免费。但 Android 端 SDK 目前做得最好的可能是爱奇艺开源的 xCrash,如果想要学习的话,阅读它的源码,应该是一个非常好的手段。
Bugly 额外添加日志文件支持得不是很好,可是很多 crash,我们往往要去日志中去寻求异常原因。所以目前我自己的异常上报方案就是使用 xCrash,在 crash 时把日志也上报一份。
除此之外,官方也在 Android 11 提供了 App Exit Reasons 这个 API, 用于我们获取用户是因为什么情况退出应用的,目前,应该主流的手机都升级到 11 以上了吧,所以它也可以用起来了,而且它的 reason 还包括 REASON_LOW_MEMORY、REASON_EXCESSIVE_RESOURCE_USAGE 等众多原因,作为数据分析,也是非常有用的。
内存泄漏
内存泄漏目前的主流分析工具就是 LeakCanary 了,所以 App 怎么也得接入下,这个也是面试官非常喜欢问的问题了,属于面试必备了,了解下其实现原理也是很有必要的。
网络监控
网络监控主要是两个点,一个是上下行流量的监控,防止开发写了有问题的代码,出现在循环内疯狂请求后台的情况,除了会给后台压力,也容易被用户投诉。emo 的 network 做了一个简易的上下行流量的采样,可以一段时间采样一次,看是否出现突发流量的情况。
另一个就是网络连接稳定、耗时的监控了,由于目前基本上都是 OKHttp 了,所以直接使用它提供的 EventListener 就足够用了,就可以把 ssl 握手时间、dns 时间、connect 时间等都统计下来。网络请求一般是非常多的,一般客户端需要先聚合下再上报给后台。
卡顿监控
卡顿监控,以前基本上就是以下两种方案:
Choreographer回调Looper自定义Printer
我们可以使用微信的 Matrix 来监控卡顿,其实现方案是基于 Looper 来做的。
后面系统提供了 FrameMetrics 接口,然后 jetpcak 开发了库 Metrics,jetpack 的实现保证了良好的兼容性,可惜目前稳定版还没到来,估计以后它就是主流了。
启动监控
启动优化也是一个重要的话题,如果首次启动时间久了,用户可能就放弃使用了。Google Play 可以采用大杀器 Baseline Profile 来优化应用首次安装后的启动时间。而国内的厂商到目前都没有追随一下的意思,所以启动耗时就依赖于业务层的改进,把能晚点初始化的东西就晚点初始化。
微信的 Matrix 也提供了启动耗时的监控,用就行了。
系统也提供了 reportfullydrawn 方法,可以由业务方来告诉系统我的数据加载完成了,从而可以报告启动到真正界面可用的时间。不过这个是为了官方提供的分析工具用的,不能直接用于线上监控。
最后
Matrix 除了上面提到的这些,还包括了:慢方法检测、APK 分析、 SQLite 检查、电脑优化、内存重复图片检测、IO 检测等等。如果是国外市场,那就可以使用官方的各种诸如 Firebase Crashlytics 服务了。
如果是真的想学习这些技术,那就去看 xCrash、LeakCanary、Matrix 源码,一切的知识尽含其中。但需要巨额的时间投入。不过已经被工作压迫得喘不过气,又哪来的闲余时间呢?大伙都在业务上卷得你死我活的,这种性能优化总会被无限期延迟,也就永远没有实践的机会。
总是背负着无尽的技术债,跪倒在一次又一次的需求变更前,过着大负大跪的程序员生活,偶尔翻看下被丢掉的计算机基础知识,以求温故知薪。
目前这个系列文章就写到这里了,之后会继续更新一些技巧与细节的讨论与思考,诸如 Compose 跨页面通信、Text 行高变更等知识。