这是鼎叔的第一百四十一篇原创文章。行业大牛和刚毕业的小白,都可以进来聊聊。
欢迎关注本专栏《敏捷测试转型》,星标收藏,大量原创思考文章陆续推出。本人专著《无测试组织-测试团队的敏捷转型》已出版(机械工业出版社)。
接上文聊聊移动APP的性能评测体系,我们继续聊聊过去十五年来,移动APP专项测试的核心指标和优化方法。
电量测试
电量的公式大家在中学应该都学过吧,电能=电功率*时间,电功率=电压*电流,一般而言,我们假定手机的电压是恒定的,那只要知道电流就可以知道整个耗电的大小,因为它跟时间是成正比的。
究竟应该怎么测试电量呢?当年我们常用的三种方法有:
一,直接读取Android API,通过和battery有关的API获取电量情况。这个方法的问题是不准,因为它是纯软件估算的,可能和真实情况有很大差距。另外,如果手机休眠时,我就没法进行电量测试了。而且,这个API本身也会消耗电量。
二,部分手机可以采用外接的手段,直接读取电池传感器,但现在绝大多数手机做不了,电池都是封装起来的。
三,采用外置的电流仪,可以进行高精度的采样,我们之前曾做了一个假电池去外接电流仪。方法三的主要缺点是专业电量仪太贵啦!
再重温一下以前的文章,当年我和武汉的小团队是怎么自制电量仪的,回想起来依然很有成就感。聊聊如何自研200元的电量测试仪
电量测试的TIPS
一,当年的手机流行超频的概念,现在好像不流行了,超频和功耗是有一定正相关的,打开超频会导致耗电增加。
二,手机屏幕的背景色和功耗也有密切关系。屏幕的亮度对电量测试有直接影响,所以我们要固定合适的亮点去做基准电量测试。
三,之前通过硬件测试电量有一个问题,它测出来的是整机功耗,而不是被测APP的功耗,但是手机能给你各个APP的功耗百分比。当然这个百分比存在一定的误差,这是没有办法避免的,APP的耗电非常微量。如果我们想用软件手段测试APP电量,可以用谷歌提供的battery historian,这是个系统级的分析工具,到今天还在使用,展示效果非常细致清晰。
然后我们还可以使用Android studio的energy profile,以及dumpsys batterystats,这就是个反馈统计结果的命令行。当然,你也可以使用当年我们TMQ团队开发的GT工具,实时在被测的APP上用浮窗展示它当前的耗电情况。
iOS这边的电量测试工具就比较少了,因为电量管理由系统严格控制(如后台应用限制、硬件模块访问权限),其电量统计依赖Xcode instrument中的energy dinosaustic,还可用energy log专门打印出跟耗电有关的日志。
如图,我每次看到谷歌的historian就倍感亲切,它能清晰展示某个进程的耗电很厉害,然后我们通过研究原因提炼了不少优化经验和经典案例,掌握好它们,你就可以成为半个电量测试的专家了。
案例一
APP在后台待机时耗电特别快。我们分析CPU的时间片耗时情况,发现某个进程中的时间片消耗特别异常,通过代码去定位问题,大概率会发现这里产生了大量的循环,然后导致功耗异常。所以正如前文所说,电量优化首先就是要减少大循环逻辑。
还有一种可能性,有一种所谓内存锁导致APP在后台无法真正进入休眠状态,内存锁会定时激活。
这种内存锁是干啥用的?鼎叔讲讲当年APP常见的流氓行为: 有些APP为了常驻内存,避免在后台挂起后被KILL掉,就在后台定时被激活,达到提高业务活跃度的目的,但这会导致手机无法真正休眠省电。
当年我带团队开发一个护眼监控APP,为了精确知道用户看了多久的手机屏幕(以触发疲劳提醒功能),就使用了内存锁功能,哪知道使用半天后手机发热,功耗严重。
案例二
跟网络切换有关的事件也会导致耗电。手机会不断发送广播或者监听广播,然后触发相应的处理。为了避免频繁的广播事件处理,开发者应该只对有效的数种广播进行响应。
案例三
跟传感器有关的耗电很常见。手机中有大量传感器在不断采集数据,如位置相关、摄像头相关、速度相关、姿态相关的传感器,相关算法调用频率也需要优化降低。
案例四
很多APP会频繁上报数据,如果频率超出预期的多,也会影响到电量,同时也会带来流量异常的专项问题。
以金融类APP为例,什么场景的耗电可能性比较大? 很明显,实时行情、交易咨询算是一类典型。用户会不断拉数据,不断去互动,导致耗电概率高。
最后,耗电的测试场景和内存测试一样,也要分为前台操作耗电和后台挂机耗电的场景。
流畅度测试
我们先看一张经典的图,手机屏幕当年是一秒钟刷新24次,连续的动画就应该是每一帧都有一些不同,如果GPU绘制卡壳了,就导致当前的这一帧保持不变,视觉上就是“跳”了一帧,形成卡顿。
补充一个知识,用FPS来形容流畅度是不精确的,FPS只是一个客观的刷新动作,它不能反映“绘制图片没有完成”的问题,所以我们会用英文单词junk来描述图片未完成刷新的卡顿,junk率就是每秒钟junk次数除以总帧数,这体现了卡顿的严重程度。我们还可以把发生卡顿的时间片总长度除以总时间,结果称为shutter率,也定量体现了卡顿情况。
还有一个和junk含义相反的概念单词是smoothness,即流畅度,如果完全没有卡顿,smoothness(SM)就是满分。以60Hz显示设备为例,如果一秒junk了5次,那就是丢了10帧,SM分数就是60-10=50。
不流畅产生的原因
第一 UI层过度绘制,同一个UI层内容被重复绘制。
第二,UI布局不合理,控件继承结构过于复杂。如果用更少的次数就能调用到叶子节点控件,UI流畅度也能提升。
第三,代码导致的流畅度问题。我们可以使用一个古老的工具Link来扫描出哪些流畅度相关的代码可以优化。
流畅度分析工具
安卓平台的流畅度主要看渲染的线程,GPU是专门用来绘图的芯片,而主线程的阻塞必然会发生一些卡顿行为。
建议大家尽量选择高精度的测试工具,前面提到一秒钟60赫兹的绘制频率,如果精度不够是难以定位到准确的卡顿地方的。推荐谷歌的实时分析工具Systrace,直到今天也是最常用工具,能够系统化地看到各个线程的渲染情况。
第二个应用级工具是Android studio里的GPU profile和CPU profile,帮助我们发现负载过高的慢线程。
第三个工具是安卓9引入的系统级综合监控Perfmon,从中也能看到一些容易发生卡顿的事件。
iOS平台的流畅度分析则依赖于XCODE生态,它提供了称为“call animation”的能力模板,我们从中观察渲染性能、触控延时、GPU负载等指标,它们和卡顿现象有密切关系。
另外还有metal system trace,Xcode debug option,这两个工具分别可以做GPU的深度分析和可视化调试。
以典型金融APP场景为例,可以重点分析:
实时行情页的K线图渲染耗时(是否因复杂路径阻塞绘制)
交易页的按钮点击延迟(如主线程被数据库查询占用)
如何优化流畅度
根据过往的多年实践经验,做一个方法提炼:
方法一,按照Link扫描代码提供的建议进行优化,简单粗暴。
方法二,用traceview工具看卡顿的地方,看哪个函数占用了更多的CPU时间片;看主线程IO操作,次数频繁也很容易造成卡顿。
我们还经常通过systrace获得运行线程和API执行信息,通过设置计时器看看程序中的具体运行时间,看看是否有重复绘制。
方法三,看磁盘的IO吞吐,这也可能给页面绘制带来一些渲染过慢的问题,这需要我们采集磁盘读写信息来核实。
方法四,有些流畅度问题来自于快速滑动场景。如用户在快速滑动屏幕时,机器性能不够,可能产生页面加载不及时的情况。我们可以采取异步加载的技巧,即在滑动过程中不要实时地显示图片,而是事后再加载。
方法五,针对前面布局层次过于复杂引发卡顿,那我们就主动减少布局层次,以及尽量复用控件,去掉多余的背景颜色。不要在线程以外再去操作UI。
方法六,最重要的仍然是,避免死循环,这是低性能的万恶之源。
流量测试
这些年随着流量越来越便宜,我以为流量测试没有那么重要。但询问APP开发leader,对方说流量测试还是非常重要的,一是不能传跟用户无关的废信息,避免让用户担心传送(隐私)数据包,二是不能重复传输信息。
在十年前,APP流量测试是很重要的。当年鹅厂有一个性能监控SDK出了一个BUG,导致用户手机一天上报了7个G的流量(都是重复的crash信息),在当时算是不小的事故了。大量传输重复数据也会导致耗电异常。
测试方法
可能有流量测试经验的读者很少,其实方法也挺简单。
方法一,抓包,如TCPDump。
首先建议关闭其他APP的联网,避免我们采集到的数据包是其他APP干的。
其次根据被测APP的UID,获取收发包的数量,抓下来分析。
方法二,长时间测试。
因为流量测试往往需要一个很长的观测时间。我们可以选择一个24小时的挂机或者重复各种操作,通过后台的固定策略去触发一定事件,避免只做“纯待机”测试。比如对一个交易APP,会定时做一些用户常见的下单和卖单操作,再检查流量是否正常。
具体用到的工具有:安卓平台上的TCPDump+Wireshark的抓包分析,另外安卓studio profile也有网络相关的数据。iOS平台封闭性比较高,不会提供太多网络包的拆解能力,所以我们会用到第三方工具,如Charles,还有XCODE instrument提供的network template模式,都能分析网络流量中的信息。
流量优化思路
提炼出以下流量优化思路,多年经验总结,条条经典:
一 对协议中的重复内容进行排重,因为很多协议消息会传递很多重复信息。我们要么降低信息发送的频次,要么就把协议内容做好归并,减少信息传递的重复率。
二 预取逻辑只在WIFI环境执行。对于不需要实时上报的信息,可以降低在非WIFI环境中发送的频次。
三 很多消息都是服务器动态下发的,我们可以对服务器增量消息做一个配置,指定特定场景才需要下发消息,避免一天到晚发送消息,同时还能保持重要的连接,达到最高的性价比。
四 很多网络请求是可以合并的,以减少发送的总次数。
五 长连接。对某些应用而言,服务端需要和客户端保持长连接,对于PUSH消息的机制而言相对省流量。
六 流量的精细化监控。分析消息的整体数据是否合理且安全,避免敏感信息被发送出去,也可以针对域名去细分流量,并判断协议发送逻辑和频次是否合理。
补充- GT工具
我们之前团队自研的开源工具GT,名气不凡,它能够在各项APP专项测试中大放异彩,不但能精准测试各种指标,还能让开发非常方便的进行性能参数调优。
下次再具体介绍GT,以及其他几个重要专项指标优化:安装包大小,弱网络,响应速度等。