一次 CPU 问题的排查
前言
最近来了个新环境,做了第一个需求——直播答题
。
这边的风格大致就是:先在能使用的库的基础上快速完成需求,整个开发时间大概在2-3周,客户端总共俩人
,我主要负责直播间内的业务逻辑。
直播间还是很简易的,没有礼物啊什么的,只有个弹幕聊天。
但是因为后端并没有长链接
,所以弹幕、直播人数需要轮训
来获取,感觉不太妙。
总之,最后算是很挫
的完成了任务吧!
收获是,了解了一些音视频和直播答题的方案(好的方案需要音视频配合,但是需要他们排期,最后用了一个比较挫,但是能用的方案),还有就是终于用上了 databinding,但是感觉用的很烂,kotlin 依然还是没在真实开发使用,主要这次有点赶,没敢用,下次一定。
但是,最终性能测试没有通过
。因为有的设备性能很差,加上系统本身有一些基础服务占用 cpu,性能测试要求 app process cpu < 60%, total cpu < 80%
直播答题的 app 因为有音视频编解码,在最低端的设备上最终 app process cpu 40%, total cpu 80.25%(超标
)
那咋办呢?
CPU 过高怎么查
作为一个合格的工程师,当然是打开了 Google -> Android CPU 过高怎么办
基本就是说用 profiler 或者 adb 命令看一下,但是并没有具体的分析。
我感觉应该分为下面几个步骤:
-
确定复现场景(哪个页面 cpu 高? 哪个场景 cpu 高?)
如果这个找不到,那根本无从查起了,比如我这边就是进入直播间 cpu 占用变高。 -
场景中有哪些消耗 cpu 的场景?控制变量,进一步缩小范围
比如我的直播间 cpu 过高的话,直播间有 轮训的网络请求、动画、播放器,这三个可能会比较耗费 cpu 的东西,分别注释掉其余两个,看看到底是谁的锅?
需要有足够的耐心! -
确定到具体的小方面,profiler 查看具体问题
我最终通过注释代码,发现大部分 cpu 是播放器的锅,但是播放器使用的是别的部门的,而且应该也是线上用的,想要给他们反馈 bug,肯定要有十足的证据。
通过前面的方法论,我当时基本确定了问题出现的场景:重新进出直播间,cpu 就会上涨 15% 左右(只上涨一次,只在一批固定低端设备产生问题)
所以,问题也很诡异,一开始反馈给播放器部门,他们尝试复现,结果并没有复现出来。
可是,这个问题不修复,总觉得好像是我不太行,第一个需求就因为 cpu 被卡了,所以只能用 profiler 来慢慢看了。
Profiler 分析 CPU
profiler 的使用就不多说了,android studio 直接使用,attach 到对应进程上就好了。
当时的 cpu 如下图:
Home 页面有一个可以预览的小的 VideoView
home(cpu 20%) -> 其他页面(静态页面 cpu 基本0) -> 返回home(cpu 36%)
具体的分析过程,用了半天左右,怀疑过各种问题
- log 里看到有播放器 error,以为是播放器出错导致(后面发现,似乎这个 error 一直有···,排除)
- 播放器部门同学说是不是存在泄漏,所以看了下内存,播放器实例,也是一个引用
- 有的小伙伴说是不是因为设备太差 GC 呢?然后图里有个 heaptaskdaemon 确实一直在运行,当时看了老久这方面
最终只好对比前后的线程数变化,最终发现了一个可疑的线程,然后通过 method tracing 发现了问题,如下图:
当 CPU 上涨的时候,伴随着这个诡异的 APM_TaskQueue 线程的疯狂运行,甚至比主线程还忙,看起来是个循环才会这样。看名字像是个队列,盲猜是一个神奇逻辑导致队列任务过多,执行任务使用的 while(true) 么?然后也永远执行不完?
然后 record 一段时间,打开具体的 tracing 看了一下,包名也是来自播放器提供的一个 jar 包内,似乎是做埋点上报的。
将以上截图发送播放器部门,他们重新出了一个包,说是依赖了这个第三方埋点库,这个库的问题导致的,最终 total cpu = 64%,通过性能测试,问题解决(但是看他们解决的速度,我咋感觉是直接把这个库干掉了?)
总结
cpu 问题现在应该基本遇不到了,只有低端设备才会出现这些问题,都是具体问题具体分析的。
基本就是围绕着 cpu、内存和帧率来看的,这几个有时候会互相影响。
我遇到的这个问题很简单,通过 profiler 就能分析的出,android 的其他的诡异问题可是太多了!令人头秃!
这个项目写完,感觉自己对于 databinding 和 viewmodel 的使用很烂。
看另一个哥们写的就很简洁、灵动。
加油呗!
生日快乐