【穿山甲系列】像修复Crash一样修复卡顿

作者:虫虫爸

团队:腾讯移动品质中心TMQ

无奈

大家在做Android项目时,是否对以下一幕感到很熟悉?

正如上图所示,我们在版本发布前,一般都会做一些性能测试,其中会包含流畅度测试。然而即使在本地测试流畅度性能指标非常的好,但还是会有不少用户会反馈出现卡顿,这究竟是为啥呢?

有人曾诙谐的把发版前的测试数据比作汽车的“官方油耗”。汽车官方油耗对用户其实没有多大指导意义,用户在实际驾驶汽车时的油耗往往高于官方油耗。同样的道理,用户使用时的情况往往会比测试结果差,主要有三方面原因。

第一,测试时使用的手机一般是在少量的机型上进行,线上用户的机器千差万别,所以测试数据覆盖不了所有用户机型。

第二,用户使用场景的环境复杂,各种因素影响较大。而测试的环境较稳定,影响因素较少。

第三,性能测试由于需要每个版本执行,往往是通过自动化测试来实施,那覆盖的场景一般是用户的主要场景,覆盖面较小。

因此,实验室环境的测试数据可以用作一个指标使用,但不能迷信这个数据。

线上用户的反馈更能反映产品的质量。

那么问题又来了,用户反馈是反映出了实际的情况,但也仅仅是说明产品质量有问题,对我们性能改善毫无用处。由于用户发生卡顿可能是在较偶然的场景,本次出现卡顿,下一次不一定能复现,当联系上用户时,他们往往又说不卡了。此外,用户反馈了问题,他们即使能很清楚的将问题描述出来,开发同事也很难定位和修复问题。

曙光

我们是否能通过线上的数据来解决用户的问题呢?

显然是可以的,不过在这之前需要解决以下问题:

  • 能收集到线上用户的真实数据并发反馈;
  • 知道什么情况下可以认为画面是“卡顿的”;
  • 如何让开发能快速定位和修复卡顿问题;
  • 如何能验证问题到线上的确是修复了。

这些问题在我们的方案中得到了较好的解决,该方案是结合穿山甲系统来实现的。

卡顿上报方案

我们的卡顿上报的思路如下图所示,我们希望在灰度阶段通过上报发生卡顿时的堆栈来定位和修复问题,并在下一个灰度期间验证问题的修复情况。

在数据上报前首先需要定义什么是卡顿,可能不同的项目组对卡顿定义是不一样的。

我们项目组将卡顿定义为当画面连续n毫秒出现丟帧,导致用户能感知到画面不流畅。这个n在穿山甲SDK初始化时设定,可以根据实际需要调整。该值越大卡顿上报条件越严苛,产品质量越低;该值越小则上报条件越低,产品质量越高。

目前我们项目组的n定为100毫秒,也就是说连续丢6帧会认为是出现卡顿。对卡顿的监控穿山甲SDK通过实现FrameCallback来实现监控。

以前在测试流畅度的时候,提供了帧率的数据给开发同事。大家可以想象一下当开发同事被告知他的代码存在卡顿,但得到的信息只是一个帧率数字时会是什么样的表情。

那提供什么数据才能让开发同事更加快速的定位和修复卡顿问题呢?

我们认为开发同事最希望告诉他们哪个位置的代码卡,甚至是具体的代码行,他们去修那段代码就行。鉴于此,穿山甲的方案采用了上报卡顿画面主线程堆栈的方法。既在发现屏幕连续丢帧时,将当时正在运行的代码的堆栈上报到服务器。

然而在项目实施时发现上报的卡顿日志很多,数量多达近6万个,如果让开发同事去一一确认显然是不可能的。为了提升卡顿问题的处理效率,穿山甲后台分析系统对上报的堆栈进行了以下的处理。

  • 按堆栈进行比较,将完全重复的堆栈先合并到一起。
  • 去掉全部是系统堆栈的日志。上报的堆栈如果全部是系统堆栈,说明是由于系统的原因引起的卡顿,开发同事对此也无能为力。穿山甲是判断堆栈中是否带有tencent字样,如果没有则丢弃。
  • 排除上报率比较低的堆栈,现在的去除策略是忽略上报率小于0.1%的日志。像我们项目Beta1版本发布20万用户,那上报次数小于200次就会被排除了。
  • 再次根据项目的堆栈进行去重。从内层堆栈开始,首先去掉了系统堆栈,找到项目代码的前3行堆栈将行号去掉,然后对比这3行堆栈,如果是一样的,则将堆栈和上报数量合并。
  • 再按开发同事给的白名单关键字,去掉忽略的堆栈,最后将剩下的堆栈排序。
  • 按开发同事提供的模块关键字和责任人信息,自动将top 50的堆栈提交到Bug系统。
  • 随着每天上报的数据增多还会定时执行分析,提交新上报的Bug,并自动更新已有Bug的上报数量。最后由于卡顿问题都是线上用户的设备上报的,卡顿问题修复后,通过本地测试是不好验证的。穿山甲的验证方法是看下一轮灰度上报的数据中,是否还存在已修复问题的堆栈来进行验证的。系统页面展示系统中对卡顿堆栈数据,经过分析后展示的画面如下面两个图所示。这两个页面主要展示了上报的卡顿堆栈的数量和上报机型数量,在详情页展示具体的卡顿堆栈信息。
    在详情页下部还对上报卡顿的设备信息进行了简单分析,如下图所示。
    除此之外,穿山甲的分析还有一个很独特的分析功能,就是用户操作路径分析。我们利用时间序列分析对卡顿发生前最近的10步的用户操作行为进行分析,可以知道用户发生卡顿时主要都做了什么操作,能让开发更加准确的定位出问题所在。用户操作的分析用操作的公共路径如下图所示。
    前面也提到了卡顿问题的验证方法,我们验证问题是否修复有两个方面,首先不再上报被认为是完全修复了;另外如果上报率有下降,则认为有一定的优化,也算有进步,不过还需努力优化;如果上报率未减少甚至上升则认为问题没有修复。下图展示了问题验证的画面。
    该方案的优点本方案主要好处有以下四点:
  • 利用灰度阶段收集到的数据基本可以反映用户真实使用情况,而且机型覆盖比较多,功能覆盖也很全面。
  • 信息反馈速度快,今天发Beta1,明天就可以看到较全面的数据报告,不用等待用户来反馈。
  • 问题解决速度快,开发可以直接根据上报的堆栈修复问题,定位精准,节约很多时间。
  • 问题修复情况验证快,Beta1上报的问题可以及时修复,然后再通过Beta2上报的卡顿数据验证修复情况。

成果

在我们项目组实施了卡顿上报方案后,效果还是非常明显的,借用一张开发同事的数据汇总列表如下,卡顿反馈数量下降约70%。

未来

穿山甲系统的卡顿上报方案可以让线上卡顿的问题用类似于Crash上报的方式来解决,让卡顿的效率得到很大的提升,但穿山甲系统希望未来能更进一步。

目前我们正在做一件事,就是尝试从大量上报上来的卡顿堆栈中学习总结出引起卡顿的原因,形成经验库。再利用经验对开发的代码进行扫描,争取能在代码开发过程中就发现类似的卡顿问题,起到预防的作用,提升我们的生产效率。

关注微信公众号:腾讯移动品质中心TMQ,获取更多测试干货!

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DevOps时代的专栏

什么是服务网格(Service Mesh)?为什么需要使用它?

在过去的一年中,服务网格(Service Mesh)已经演变成为云原生堆栈的重要组成部分。像 Paypal,Lyft,Ticketmaster 和 Credit...

2226
来自专栏北京马哥教育

小白用Python | 桑心病狂,试试把报警信息发到微信上

? 前言 笔者所在公司项目的报警信息会通过钉钉发送到群组或个人,这样如果服务出现了问题我们都会第一时间收到提醒并进行处理。 某日从钉钉收到报警信息的我突发奇想...

3507
来自专栏Golang语言社区

微服务架构的优势与不足

英文原文:Introduction to Microservices   这篇文章作者是Chris Richardson,他是早期基于Java的Amazonit...

3175
来自专栏IT技术精选文摘

京东网络接入体系解密之高性能四层网关DLVS

DLVS诞生之初 在SLB这块,京东用户接入系统提供四层负载均衡服务和应用层负载均衡服务,对于公网流量接入部分,和很多公司一样采用的是四层和应用层负载相结合的架...

2909
来自专栏纯洁的微笑

一文读懂 Spring Boot、微服务架构和大数据治理三者之间的故事

814
来自专栏开源项目

用大白话聊聊分布式系统

一提起“分布式系统”,大家的第一感觉就是好高大上啊,深不可测,看各类大牛关于分布式系统的演讲或者书籍,也大多是一脸懵逼。本文期望用浅显易懂的大白话来就什么是分布...

3659
来自专栏IT技术精选文摘

PB级海量数据服务平台架构设计实践

基于PB级海量数据实现数据服务平台,需要从各个不同的角度去权衡,主要包括实践背景、技术选型、架构设计,我们基于这三个方面进行了架构实践,下面分别从这三个方面进行...

2326
来自专栏织云平台团队的专栏

8分钟丨教你玩转 API

1612
来自专栏Java技术交流群809340374

实战讲解高并发和秒杀抢购系统设计

互联网特别是电商平台,阿里双11秒杀、还有12306春运抢票、以及平时各种节假日抢购活动等,都是典型的高并发场景。

340
来自专栏ThoughtWorks

Web App性能优化之亮剑|洞见

自计算机诞生以来,系统性能问题亘古未变,从指令级优化到集成系统的优化,可谓愈来愈复杂。每种类型的性能问题即便出现的场景不尽相同,但依然有一些性能优化模式,久经沙...

3256

扫码关注云+社区