活动背景
移动互联网时代,各大互联网公司都已将自己的产品和服务全面移动化,各类新产品功能都会优先在移动APP上尝试。
应用性能作为影响用户体验最重要的因素,在开发过程中显得尤为重要。
● 用户网络环境不稳定,兼容性差?
● 终端设备碎片化,iOS/Android跨系统开发问题多?
● 怎样才能打造出优质的移动应用?如何才能避免产品运行缓慢和卡顿?
……如果这些话题你感兴趣,不妨来极光开发者沙龙坐一坐,本期我们邀请到 沪江、饿了么、阿里巴巴的技术大咖,与大家一起用实例进行解析,围绕移动应用性能质量,从移动端SDK优化、移动端APM性能监控、APP深度性能测试等几个层面分享关于优化产品、提升性能的技术干货。

主持人:第一位分享的嘉宾是来自沪江高级Android开发工程师徐宜生,他演讲的主题是:移动端APM性能监控

徐宜生:大家好!首先感谢大家在工作日能抽空来参加这样一场技术沙龙,感谢大家的到来!
我今天讲的题目是移动端APM性能监控,在很多年以前我们对APP的使用好与坏的评价是通过它在使用过程中会不会发生崩溃来评价。但是这么多年过去了,APP的开发技术更加成熟,一个应用在使用过程中是否崩溃显然不足以座位我们评价这个APP好与坏的标准了,现在会通过用户的使用体验来评价APP好与坏的标准。

首先自我介绍一下,我叫徐宜生,是沪江的Android开发工程师。这是我写的两本书和我的公众号,感兴趣大家可以关注一下。

我们首先来看一下APM的定义是什么,我们把APM系统定位为对应用的性能、可靠性进行线上的监控和预警的机制,通过APM系统来完善和统一一整个流程,让我们去发现新的问题,分析新的问题,解决新的问题,这是整个APM存在的意义。

APM系统到底有哪些作用呢?我这里简单地列举了几个,第一个说我们可以监控线上APP的质量,对崩溃和异常数据进行分析,这是APM系统最大的作用。通过了解这些数据了解我们的APP在线上用户真的使用的时候到底会不会存在问题。

可以通过数据的分析提前预警可能大范围爆发的问题,通过数据监控发现可能某一段时间有一些异常的数据量会有上升的趋势,会提前对它问题进行分析,采取解决办法。比如说调整一下后端的逻辑或者是通过客户端发补丁包的方式避免大范围爆发的“灾难性的问题”。
我们可以通过后端优化负载,提升服务器性能,让APP的性能得到非常好的提升。我们是站在技术开发者的角度通过提升APP的质量和体验提升用户的使用黏性,这是我们做技术的人帮助APP去提升用户使用黏性的方式。用户对产品会非常感兴趣会使用它,同时在使用的过程中使用的很舒服也是使用它比较重要的原因。

沪江的APM系统建立了两条指标体系,一条指标体系是横向基线指标,另外是行业的基线指标。横向是每一个APP不同版本之间的数据对比,座位横向比较的分析基线,行业基线是沪江自己的APP和竞品的APP,比如说开营职场(音)之间的竞品性能的对比。中间是我们APM平台,通过APM平台把数据做分析汇总,通过对数据的分析去找出潜在的性能问题,交付工程师进行修复和优化。这是整套APM系统的大概体系和流程。

APM系统是一个前后端都非常复杂的一整套系统。我主要来讲解一下后端上的实践。后端也会有很多的问题,都在探索过程中。这里我列举出了几个APM技术上实现的难点。

第一,Native、Hybrid混合编程对数据采集的影响。最重要的问题是Android系统的碎片化。不管是Android版本的不同或者是不同的ROM厂商他们之间对APPROM的修改,这对我们采集APP的性能都会有或多或少的影响。不像IOS在性能监控方面好一点。
第二,如果通过后端SDK的方式去监测性能的话,对诉主来说性能是有直接或间接的影响,同时APP介入APMSDK的拓展性、可制定性都是我们需要考虑的。
第三,APM后端数据分析,前端负责采集性能数据,采集好之后我们需要把性能数据上报给服务器,在后端做可试化的分析,从数据里面找到潜在存在的问题,这也是比较大的难点。
第四,性能数据监测链路太长。因为我们在使用APP的时候,APP本身有很多界面,也有很复杂的网络请求,从服务器里面分析数据返回数据再重现展示,整个链路都是非常长的,在链路中每一步都可能发生新的问题,所以都需要进行监测。
第四,不同的性能日志互通比较困难。在后端的开发中已经有很多的性能日志,比如说接口日志、服务器的放态日志。前端也有自己的日志体系,比如说性能日志和请求日志,都非常多,但是我们没有能够将这些日志串联起来的方案。比如说我们在前端碰到一个用户发现他在使用APP的时候异常地卡顿,但是我们没办法把后端的日志和接口日志整合起来分析原因,我们只能通过前端上报日志来定位问题,这也是我们APM技术的难点。

下面来看一下APM的系统,主要对性能的监控有哪些监控的维度。

第一是内存。内存对我们APP性能影响的重要性应该是毋庸置疑的,它直接影响了整个APP的交互体验,主要是APP使用的流畅度。除了流畅度以外APP的内存也会对系统产生影响,同时也会应影响ROM对你APP后台状态的管理,都会造成很大的影响。

内存主要通过四方面,内存峰值、内存均值、内存抖动、内存泄露来判断。内存抖动是有波峰波谷的抖动,如果发生了内存抖动的话代表我们现在的APP在操作方面有不太合理的操作,这会导致内存频繁地升级和释放,如果你APP在使用过程当中内存抖动非常多,肯定会有很大的卡顿。内存泄露讲的比较多,如果APP泄露的话导致内存上升,如果不释放会影响整个APP的体验。

我们处理内存监控的时候主要通过Runtime获取内存,Android还提供了其他很多类,比如说Meminfo去获取内存信息,或者通过Android底层的内存文件去获取内存信息。综合比较下来选择使用Runtime去获取内存信息。通过这种方式获取的内存信息比较符合APP实际的操作体验。它与我们在Android里面监测内存的数据也是很符合的,所以最后选择采用通过Runtime去获取实时性的系统。通过Meinfo去获取信息,通过它提示给我们的信息把数据做汇总上报。

CPU和内容也是APM监控的重点,CPU是整个安卓手机里面比较重要的资源体系,它会影响用户使用APP的发热和卡顿。发热很好理解,CPU的耗电量是非常大的,除了屏幕以外最大的发热就是CPU。卡顿就是CPU在不停地处理事情,会导致它的渲染时间很长,导致APP的卡顿。

CPU主要通过CPU峰值和CPU均值去判断CPU的健康程度。峰值很好理解,如果CPU发生了峰值肯定是有比较合理的操作,我们可以看是不是有这样的操作,CPU均值是考虑到整个APP的发热量,不可能让一个APP在使用过程中它的CPU始终保持在很高的水平,这样是有问题的。CPU通过是通过RUntime获取内存,通过也通过Proc获取实时的CPU数据,当前的使用量、百分比都可以拿到。

下面列出来的是APP的启动时间,启动时间在之前的开发过程中这个问题不是很严重,因为现在第三方的SDK越来越多,而且第三方的SDK大多数都需要做数字化,接触的东西多。像我们第三方的SDK有几十个,加上我们自己的SDK,所有的东西进行初始化会非常耗时。最初会做延迟的初始化,或者是做异步的初始化,避免其中的初始化导致的耗时。

启动时间列出来三个,一个是冷启动时间、热起动时间,页面渲染时间。冷启动时间、热启动时间是我们比较关心的两方面,是用户第一次打开APP的第一印象。冷启动是APP的进程没有被创建过第一次电极到页面展示所耗的时间。热启动是进程空间已经创建好了,直接换APP所耗的时间。一般来说热启动时间大部分的APP时间都差不多,冷启动时间差别还是很大的。

像我们之前跟行业上的竞品测试来看差距非常大,有的冷启动时间能达到2到3秒,有的只要几百毫秒。这些看似不起眼的数据就是用户选择使用某一款APP比较主观的感受。之前开发APP的场合现在已经不仅仅是业务上的竞争了,更是性能上的竞争,这些东西都需要我们一点点去积累。性能监测、性能优化也是从量变到质变的过程。只有你每个地方都去研究一些很小的性能,最后会带来很大的提升。

页面的渲染时间是我们在APP使用的过程中从一个界面切换到另外一个界面,另外一个界面从启动到绘制展示完整的时间。页面渲染时间就非常影响到我们用户去使用APP的一个想法。比如说以前我们去打开网页,这个网页加载速度特别慢,要3到5秒才会加载,很多人第一时间加载不出来就把它关掉了,APP的启动也是一样的。一个页面切换的时候需要很长时间才能加载出来,而且非常卡我们都没有了使用兴趣。冷启动和热启动时间通过AM Start去监测它启动时间。还有是通过AOP切入生命周期,通过这个方式计算启动时间。这两个方式各有利弊,后面会进一步分析。

UI性能是比较重要的一个部分,因为CPU和内存都跟系统有关系,不同的安卓版本还有手机ROM对内存的控制策略都是不一样的。比如说你三星的手机砝码在不同的ROM场上会做调整,比如说安卓的系统版本4.4或者5.5以上的虚拟机内存分配是有不同的策略,所以这些东西跟系统都非常相关。但是UI性能是给用户最表面最直观的感受。一个APP可能业务上不是很满足我的需求,但它不能卡,如果特别卡业务部满足我的需求我可能不会用它了。

前两年的手淘大家可能都用过,在安卓上会非常卡,如果你不是特别喜欢买买买的小伙伴,我觉得我都不愿意使用淘宝,我宁愿用PC版也不愿用手机版,现在手淘版的UI性能好很多了。这也能体现我们对性能的重视程度。最近谷歌IO刚结束,谷歌已经对性能这一块儿非常重视,它已经集成了性能的监控,但它东西比较少,现在目前只有内存、CPU和网络做了监控。可以看得出谷歌对性能这一块儿是非常重视的,谷歌今年IO也有将近7、8个都是讲如何帮助开发者提高应用的性能。如果大家对这一块儿比较感兴趣的话可以看一下IO的视频。前两年谷歌也一直推安卓的小的短视频,都是提升APP性能的方式。

UI性能非常重要,主要是这几个方面,重绘的性能、滚动帧率还有ANR包括页面渲染时间。UI性能这一块儿重绘性能大家都很熟悉,比如说我现在在一个背景上画一个列表,这个列表的背景已经把我本身的APP的背景盖住了,系统绘制的时候只需要绘制一个就可以了。GPU在绘制的时候已经做了优化,所以重绘性能可以降低。滚动帧率是UI系统的重点,列表不管在哪样的APP,列表里面都是有的。滚动展示UI的时候一定不能卡,这是我们评价UI性能是否好的最直观的体验。如果你拿一个旗舰机去运营你的APP,你发现在滚动过程中特别卡顿,普通用户在使用的时候是更加不可接受的,这一点要做到保证能够达到60帧以上的。

ANR是页面的未响应,对用户体验是非常不好,主要通过这几方面去监测UI性能。UI性能有很多监测的方式,通过Handler Log printer的方式,可以做UI性能监控的核心原理。另外是通过Choreographs进行监测,这是系统在每一帧的回调。最后FrameMetricsAggregator,这是谷歌今年新加的类,通过这个类可以让我们在代码中直接获取到UI相关的绘制性能。大概看了一些,有帧率或者是绘制的响应时间,这些数据都能拿到。这个东西跟我们之前通过APP获取数据有点类似。我们后面通过这些可以直接拿到数据,更方便我们做UID性能监测。

下面的监控维度是耗电量,这是大部分用户特别厌烦的原因,我这个APP可能不是很好用,但是我一天两天也用不到一次两次,但绝对不能在我的手机里面特别特别地耗电,现在APP手机电能不能撑一天是人生最基础的需求,如果一个APP特别特别耗电的话,基本上不好用。耗电这一块儿主要是两个方面,一个是耗电量一个是发电量,这两个东西是息息相关的,耗电量高发电量一般都会高,不能使用你这个APP的时候明显发现手热,这也不行。
耗电量主要通过这几个方面,一个是WakeLock监控,申请CPU的使用,导致CPU持续被我们用,即使我们没有做高密度的计算,同样也是在占有这个CPU,在耗电。

另外通过BatteryManager获取电池信息状态,另外是通过谷歌提供的数据BatteryHistorian监控耗电,它可以提取我们APP在每一个阶段的耗电量,可以判断出是什么东西耗电。比如说是Wifi请求、屏幕的展示绘制都能分析到,通过这个报告可以查找我们的APP是否具有耗电的问题。

这里还列举出来一个我们所监控的维度,网络性能。现在大部分的APP都是强网络相关的,大部分东西都需要去联网。联网不可避免地带来网络上的问题,特别是国内的网络环境特别复杂,存在很多运营商劫持或者是弱网、区域网各种网的问题都非常多,不像国外4G的信号覆盖的会非常广,像我们这边经常到地铁上就没信号了,弱网和区网的环境都非常多。

我们不仅要监测网络的性能,同时也要监测网络的错误。比如说DNS、运营商的拦截,相信大家在APP里面都遇到过,还有请求流量的大小,能够尽可能地降低请求流量。接口的往返时间、首包时间,还有接口的异常数据、服务器的异常数据。你可能发一个请求,服务器那边认为它收到这个请求这个接口就是通的,但实际上它收到请求以后处理问题有问题,所以我们也需要对这些东西做监控。

监控网络主要通过AOP的方式做网络的请求接口的拦截,因为我们在使用APP的过程中做网络请求,我们没办法在里面去打点,可以通过不影响业务线的代码直接通过AOP的方式做埋点,这样不用改代码,他们也不会有什么抱怨,你就可以拿到网络的请求数据。

光有网络请求数据也是不够的,因为这些网络请求是比较客观物理的事件,作网络请求里有很多非客观的因素,比如说非错误的状态,服务器的返回错误状态,或者是网络运营商返回的错误状态,还有跟业务相关的错误状态,这些东西对我们去分析网络问题也是非常有用的,这些东西也需要通过把状态捕获到,加入APM监控的体系当中去,帮助我们分析问题。另外是服务端的日志分析,服务端的日志是非常丰富的,但它跟移动端结合起来会比较少一点,我们会通过打通日志的方式,通过移动端的时间、用户ID去找到服务端内置请求具体的请求日志,从而分析问题。网络这一块儿相信大家会非常重视这一点的。

最后列举出来的是用户的行为路径,就是一个用户在使用这个APP的时候先打开了某个页面,点击了某一个按纽,在这个页面上停留了多长时间,做了哪些操作。我们为什么要做这些操作呢?它跟APM并不是很相关,但通过监测用户的使用路径了解用户都使用了哪些方面,后面可能会把我主要的精力放在优化页面的性能上去,可以提高做性能优化的效率。

同样,用户行为路径是通过AOP的方式做用户点击路径的操作。如果你为了这样一套APM体系还要让业务线加很多代码,他们工作量会非常大,也会非常抵触。你没的东西他们抵触已经很大了,再加这个抵触会更大。所以我们主要通过AOP的方式做监控,AOP在性能监控里面是非常重要的一方面。我开了一个户,里面有常用的操作,让AOP的相关方式变的操作一点。

我们APM平台分为两个部分,一个是客户端的性能监测SDK,一个是PC端的性能监测。为什么分这两部分呢?它们各有利弊,我们没有找到比较好的方案能够一套就完全拿到它们的优点,摒弃他们的缺点。

在线上阶段我们可以通过客户端的性能监测SDK,通过APP做性能的监控,优点是不受设备限制,它的缺点是宿主APP代码有侵入,对性能有一定的影响。同时它也需要宿主去接入代码,它对代码还是有侵入的,没有办法做到无痕切入。

在内测方面会通过PC端的性能监测,主要是借助APP的命令去做性能的监控。做一套可试化的工具,通过工具去分装一些APP命令。它的好处是不会影响性能,因为它直接通过PC端APP跑获取数据,它也不需要侵入代码,而且它也可以测试竞品,可以做对比。但是它唯一的缺点就是它需要连接APP,限制它必须得在一定的范围内去做测试。这是它的优点和缺点,综合这两种方式的优点缺点,最终采用两套不同的性能监测的方案去做性能监测。

前面讲的都是我们如何去采集监控的数据,真正采集到数据之后我们需要对收集到的数据进行可视化的展示,便于我们做数据分析,从海量的数据里面找到潜在的问题以及我们所需要的信息。展示这些数据有好多种方法,比如说我们通过第三方的数据引擎或者是通过ELK或者生成性能报告,都可以将这些数据可视化,找到我们所需要的性能问题。这是我们测试的时候所生成的一张比较简单的性能报告,时间比较短数据会比较少。上面是我们测试设备的信息,因为我们安卓端碎片化太严重了,机器和版本都特别多,我们在做性能测试的时候最好结合某一种机型或者是某种系统去做对比,因为可能一个旗舰机和山寨机的性能表现肯定是不一样的。

中间这一部分是性能参数,性能参数包括了用户的行为路径,通过它的行为路径做采集的性能参数,性能参数就是我们前面所提到的监测维度,下面是启动时间和渲染帧率,生成了非常简单的报表。因为这套系统还没有开源,我们还有很多事情要去处理,目前这套系统还没有达到我们比较满意的状态,所以我们暂时还没有开源,但我们在后端使用的是ELK开源数据展示的集成方案。

这里我在网上找到了两套比较符合现在平台的界面,给大家先展示一下。这是Kibana的界面,它通过数据做可视化的展示,通过非常方便定制采集到的数据,可以做监控。它的搜索能力和展示能力都是非常强大的。这是ELK的展示图表,不光展示到可视化的数据,可以把详细的数据表现在下面。我们对ELK做二次开发,通过ELK把前端后端的日志进行打通,可以进行关联性的操作,方便我们做性能数据的分析。

APM系统说大也不是特别大,说小也不是很小。有很多东西是我们需要去完善的,我这里列举了几个后面会进一步优化的点。比如说我们准备结合AI,结合现在比较火的人工智能的方式去分析数据的Pattem,因为不同的性能问题、数据表现是存在内在的观点的。有经验的程序员看内存的数据可以直接定位到可能发生性能问题的具体原因是什么。这是有经验程序员和没有经验程序员非常重要的区别,我们可以借助AI找出数据之间的观点,可以帮助我们更好地更加高效地分析性能问题。

本地异常数据的监控算法。如果APM的SDK导致了整个APP的性能问题,它本来是做性能监控的,结果导致了性能问题。我们需要有一些调度算法,更加智能地去控制,比如说这个APM系统当前出现了未知的问题,我们可以自动地停止它。或者我们在采集数据的时候发现数据有非常大的风险和问题,我们可以采取本地的策略,让它能够自动降级,或者是切换不同的服务器做本地异常的监控。异常数据的预警和服务端的指令功能现在基本上已经实现了。异常数据预警借助ERK系统,可以帮我们做异常预警,一旦发现某一种情况的异常有可能上升的趋势,我们就提前去发邮件发微信告诉开发即使去调整策略,解决新的问题,避免大范围地爆发。

服务端指令控制是我们去收集日志更加精致的方法,很多性能问题都是不可浮现的。我们大部分时间都会通过日志的方式去做分析,日志上传又不是实时的,只有在积攒到一定的量的时候才会上传。通过服务端的指令控制,一个用户发来问题,我们可以通过服务端主动地搜索信息或者是打开开关做监控,了解到更详细的性能信息,帮助我们去排查问题。

自动化测试平台对接。APM系统在内测方面会通过PC端的方式做性能监控,也通过APP方式做性能监控。它和自动化平台对接之后可以做到发内测的包通过编译、打包发布到自动化测试平台,去运行它的自动化设计脚本,在这个时候我们把性能数据全部都挖掘出来,这样可以在内测方面非常方便地获取到数据,而不是用户怎么去测,这样测的不太一样,每个人关注的点也不一样,通过自动化测试平台可以24小时不间断地找到问题。这套方案现在正在做,马上也快做好了。
我今天的分享主要就是这些,大家有什么问题吗?可以问一下。

提问:徐宜生,我有三个问题。首先这个东西Android有了,IOS有吗?
徐宜生:Android有了,IOS一般都能实现,Android拿到的数据更丰富一点
提问:如果作为用户路径每一个页面都有标准的联系,你这个数据是后台直接把数据映射出来呢?
徐宜生:我们是在客户端做的,服务端做的代价会已经大。通过AOP的方式做,在不改动现有的业务代码的基础上通过AOP的方式专门有一个文件,专门做切入。
提问:数据未压缩前是2400,压缩后是用什么跨平台的?
徐宜生:性能监控的数据是采集数据非常大,如果通过文件的方式去做确实不是很好,因为它占用体积。我们现在还是通过采集数据做的,因为我们这套方案还没有大范围地铺开,只是在1、2个APP上做事情再进一步优化,后面会通过APP的方式做数据优化。我们这些数据基本上都是数字,很简单的数据结构。
提问:结合第二个问题,这个东西的量还是蛮大的,是在什么情况来控制它?用ELK?
徐宜生:流量控制服务器会下发一个策略,这个策略是在服务器上配置,在客户端会去做策略更新。
提问:感谢宜生!

提问:问一下关于异常数据预警,我印象中这个东西有异常会实时上报,是我本地有小东西在做预警?
徐宜生:客户端本地做预警量不是很大,只有达到一个量的时候才会做预警
提问:这个预警怎么限制?
徐宜生:可能今天下午发现数据端已经起来了,可能是早上的数据,还是是有一些延迟的,基本上做到实效性高一点。
提问:还有是关于PC端的ADB,有没有试过有些原生的厂商会有自带的系统,用那个东西去抓,因为它对性能也会影响,不是太清楚。
徐宜生:对,像LTC会有自己的性能源。有两个问题,一个是测试机可能有高端的有MPV的,没有办法做统一。另外数据没有接口能够给到我们,像写日志,日志要么就是加密、压缩的,格式也不是很解析。但我们在使用过程中也会用到像高通的工具,我们早期地时候也结合它去做东西,返回它的APP,看它是怎么用的。高通的CPU提供了SO,那个科技度更加细一点,它在CPU里面已经预留了一些东西,我们把数据拿出来就可以了。
像现在从Android2.4以后也非常详细的工具,它监控的APM数据跟我们现在监控的维度都是差不多的,但是唯一的问题也是数据没有办法导出来,我们现在也在考虑如何通过工具把数据导出来,这样我们可以更完善这样的方案。之前是通过DDMS做的,找出它怎么去监控性能,它的AD性能把它拿出来。如果我们能把Android的系统拿出来的话,这个东西会变的更好。

提问:PC端是通过什么获取数据?
徐宜生:通过APP。可以拿到CPU指令。
提问:其实就是写在系统里的一堆文件。
徐宜生:对。

主持人:因为时间有限,还有最后一个问题,有没有小伙伴有问题?如果没有的话大家可以私下找我们的老师去沟通。

徐宜生:PPT后面会分享出来,大家有什么问题可以加我微信去探讨。