【腾讯优测干货分享】如何降低App的待机内存(二)——规范测试流程及常见问题

时间:2023-03-08 16:11:45
【腾讯优测干货分享】如何降低App的待机内存(二)——规范测试流程及常见问题

本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/806TiugiSJvFI7fH6eVA5w

作者:腾讯TMQ专项测试团队

导语

最近小优听说,隔壁的腾讯TMQ团队出了一本新书——《移动App性能评测与优化》,便借阅了一本,读完感觉写得确实很赞。这本书体系化地介绍了移动应用性能评测与优化的方方面面,如内存,电量,流畅度,导航,网络优化和安装包瘦身等,强烈推荐大家阅读~

小优从书中摘取了第一章 “越用越卡为哪般——如何降低App的待机内存” 的内容。

本章介绍了各种内存使用情况分析的方法和一些优化技巧,让大家能够准确地了解应用内存的消耗情况,找出存在的内存问题,并在开发过程中尽量节约使用内存。

本章共5节,上周给大家推送了第1节“内存测试新手入门”的内容,本周我们继续讲解“规范测试流程及常见问题”,一起来看看吧!

1.2规范测试流程及常见问题

最开始进行内存测试时,我们可能还有些摸不着头脑,试着找了些工具,看了看教程就开始动手了。有时候因为问题比较明显,就真的发现了问题。再之后遇到类似的测试需求,我们就会按上次的经验去做。有时候可能发现问题,也可能发现不了,还有些时候发现是甚至是在白费功夫。因为随着明显的问题逐渐被找出来,剩下的有都是更加复杂而不太明显的问题,甚至有些更是可以归属到优化范畴或者产品策略之内,而不再是简单的内存问题。

随着经验的逐渐增加,我们逐渐意识到,以前的很多测试方法都是随机乱测。对于较为成熟的软件,这类方法的测试有效性往往比较低,运气好了才会遇到问题。如果是较深层次的问题要么遇不到,要么遇到了也找不出原因。因此,有必要总结出一套成熟的流程方法,能够考虑到各个方面,提高测试的有效性。

1.2.1测试流程

由于内存测试属于性能测试,Android系统又和Linux有很多相通之处。因此我们可以参考常见的Linux性能测试方法和指标,来制定客户端性能测试方案。常见的测试方法包括Monkey/UIAutomator类的常规压力测试,大数据/操作的峰值压力测试,长时间运行的稳定性测试等。这些方法都可以叠加在内存测试的方案中,观察这类场景下的应用内存情况,经常能够发现类似内存泄漏或OOM的问题。

参考了常见性能测试的方案,以及总结了以往对内存性能测试的经验后,我们总结出了一套进行内存测试的经验流程,供读者在制定测试计划时参考。

1.代码

通常用来进行内存测试的版本是纯净版本,不应该附加多余的Log和调试用组件。例如有些情况下,为了测试界面延迟/函数执行时间等性能,会加入一些桩点代码。在内存测试中这些代码是不必要的,它们可能会分配临时内存,引起更多的GC,导致应用出现运行缓慢、卡顿等现象。

2.测试场景(来自于经验&开发)

测试场景通常有两类,一类是当前有新开发或改动的某项功能,需要对该功能进行性能测试。因此测试场景主要针对该功能组织,包括功能的开启前,运行,结束后等测试点。

另一类是整体性能,考察应用的常见场景,在综合使用情况下的性能指标。测试场景应当包括启动后待机,切换到后台,执行主要功能,以及反复执行各功能后。

在各类场景中,经常做为测试重点的有:

  • 包含了图片显示的界面
  • 网络传输大量数据
  • 需要缓存数据的场景
3.场景转换成用例

选取了测试场景后,用例设计也要考虑内存测试的特点。一些常见的方法是:

  • 结合场景比较操作前后或不同版本的内存变化
  • 显示多张图片的前台进程
  • 多个场景来回切换
  • 长时间运行进程的内存增长
4.执行

由于GC和广播机制的存在,应用内存通常都在不停得波动,幅度可能会达到几百K,因此执行时需要考虑这种情况。在采集数据时,需要多次采集并计算平均值。

执行完成中,我们就可以根据数据进行比较初步的分析以确定方向。一方面是我们熟悉的Dalvik Heap部分,既由Java代码直接分配的内存,可以通过IDE直接观察到使用情况,也可以使用MAT进行细致的分析。

另一方面,假如我们发现Dalvik Heap没怎么增长,而其他部分增长了许多,这种情况下的分析就要复杂一些,我们留待后面的章节再说。

1.2.2 Dalvik Heap的常见问题

随着测试的执行,随之而来的就是一大堆产生的数据,对产生的数据进行分析,找出可能存在的问题,以及问题可能的原因是接下来的重点。

由于大部分Android应用是Java代码开发的,所以Dalvik Heap内存出现问题也是最常见的情况。常见的现象有以下几种:

  1. 随着功能的反复执行,Heap内存一直在持续增长。这种情况通常是出现了内存泄露,这种情况最适合用LeakCanary等泄露检查工具进行白盒测试分析。

  2. 代码执行时出现了频繁的GC,Heap Alloc内存大幅度波动。这种情况通常是分配了许多临时变量或数组,随后又被迅速回收,这种情况在确定具体场景后适合使用Heap Viewer / Allocation Tracker等工具来查看具体分配的对象。

  3. 每次启动应用后,Heap内存相比以前版本稳定增长。这种情况通常出现在启动后待机或使用某功能后,可能是由新功能及代码改动引入的固定内存增长。这种情况适合获取Heap Dump后进行多版本或功能使用前后的对此,能够迅速找到增长原因。

  4. Heap Alloc变化不大,但进程的Dalvik Heap PSS内存明显增加。这种情况比较少见,是由于分配了大量小对象造成的内存碎片,在后面的章节里会详细讲解,具体内容请见下一节。

1.2.3 示例

在1.1节,我们已经介绍了出现内存泄漏时的问题现象及分析方法,在这里我们再以一个真实的例子介绍常见的几种内存问题和分析方法。

这是发生在手机管家4.x的某个版本上的案例,新版中加入了一些功能,开发人员估计新功能可能会分配几十到几百K的内存,因此我们来进行内存方面的测试验证。当新功能的代码合入后,我们发现应用启动后的内存增长超过了2M,这可大大超出了所有人的预期,一定是有什么地方出了严重的问题。

由于新加入了好几个功能,因此要逐个去排查。如果某个新功能的代码都在同一个package下,那么就可以使用MAT的过滤功能来验证这部分代码是否使用了内存。如图1-7所示:

【腾讯优测干货分享】如何降低App的待机内存(二)——规范测试流程及常见问题

图1-7 使用MAT的过滤功能

经过一番筛选排查,发现内存中多出了一些新对象,多消耗了约300K内存,目前这并不能解释内存增长了2M的原因。但仔细检查多出来的对象并清理掉不用的部分也是有帮助的。

经过检查,这部分内存是其他新功能使用的。对此我们需要进一步确认,这些对象是否是有用的,还是临时创建的。对于临时创建不再使用的可以主动销毁,而保存着信息将要用到的也可以进行进行压缩裁剪,以进一步减少占用的内存。

在以上排查中,我们确实发现了一些问题,但将一些不用的对象清理后再执行测试,总体内存并没有出现明显的减少。现在看来,Dalvik Heap里分配的内存并没有增加许多,说明问题是不能只在Dalivk Heap里就解决的。也许是别的部分出现了问题?接下面我们就继续深挖下去。

1.2.4 新的问题

经过上一轮的优化,在内存监视器里新版本的Heap内存表现已经比较好了,新功能只消耗了几十K到上百K内存。但是要注意的是,Heap内存并不是应用的全部,我们在设置或其他管理工具里看到的应用内存是应用整个进程的内存使用量。也有可能出现Heap部分完全没有增长而其他部分增长的情况。

要观察进程的内存使用情况,就需要用到其他的观测工具,Android里最常用的观察进程内存的方法就是dumpsys meminfo <package name|pid>命令。

对我们的新版应用执行该命令,能够得到以下的输出结果:

【腾讯优测干货分享】如何降低App的待机内存(二)——规范测试流程及常见问题

在以上输出结果中,左边Pss Total列的数据标识进程各部分对真实物理内存的消耗,左下角的TOTAL值就是我们在各种管理工具里看到的应用内存消耗。

而Android Studio等工具里显示的内存值,在这里是Dalvik Heap Alloc部分。根据以上的数据,我们可以看到Dalvik Heap和Heap Alloc不是相等的,而且除了Dalvik Heap之外,还有其他很多部分也会消耗内存。

这时候我们再对比一下旧版,看看是否也如此:

【腾讯优测干货分享】如何降低App的待机内存(二)——规范测试流程及常见问题

这时候就会发现问题了,Heap Alloc没增加多少,但Dalvik Heap Pss却涨了许多。而其他部分基本保持不变或有少量增长。可见问题还是出现Dalvik Heap部分,但只靠检查分配的对象是看不出来问题的。

Java代码的内存分配和释放都是由虚拟机管理的,那么这个问题会是虚拟机的问题吗?下一节我们来继续通过虚拟机部分机制的探索来探索这些内存增长的原因。


更多精彩内容欢迎关注腾讯优测的微信公众账号:

【腾讯优测干货分享】如何降低App的待机内存(二)——规范测试流程及常见问题

腾讯优测是专业的移动云测试平台,为应用、游戏、H5混合应用的研发团队提*品质量检测与问题解决服务。不仅在线上平台提供app自动化测试、云真机远程操控与调试、私有自动化测试工具XTest等多种质量检测工具,更为VIP客户配备了专家团队提供定制化综合测试解决方案。