Android性能测试——发现和定位内存泄露和卡顿

2023-09-20 18:04:34 浏览数 (1)

来源:http://www.51testing.com

背景介绍

Android用户也许会经常碰到以下的问题:

  1)应用后台开着,手机很快没电了——应用耗电大;

  2)首次/非首次启动应用,进入应用特别慢——应用启动慢;

  3)应用使用过程中,越来越卡——CPU能力不足/内存泄露;

  4)应用页面卡顿——帧率较低、页面卡顿。

  因此,对开发的Android应用,必须对其进行性能测试,不然将会直接影响用户体验。

  Android应用性能测试通常包括:启动时间、内存、CPU、耗电量、流量、流畅度等。我们将在这个月陆续为大家简单介绍一下每个测试点的常见测试方法及简单的定位思路,仅供参考。之前两周内,我们为大家介绍了启动时间、内存&CPU测试方法,本期我们介绍Android测试的难题——内存泄漏和卡顿。

内存泄露

  内存泄露方面使用MAT工具定位分析。

  准备条件:

  1)手机是开发版room(建议使用小米的开发版room)

  2)手机开启root权限,可以下载一个root explorer获取root权限

  操作步骤:

  使用Androidstudio—>tools—>Android Device Monitor->进入DDMS

  1)界面中选出应用程序的包名

  2)点击Update Heap来更新统计信息(实现界面操作)

  3)开始进行测试,测试结束后,点击Cause GC

  4)点击Dump HPROF file,将该应用当前的内存信息保存成hprof文件

  图1

  如果是用 MATEclipse 插件获取的 Dump文件,则不需要经过转换,Adt会自动进行转换然后打开;如果不是DDMS Dump 出的文件要经过转换才能被 MAT识别,进入到android sdk提供hprof-conv工具目录下,(一般位于sdk/platform-tools下)。输入命令 ./hprof-convxxx-a.hprof xxx-b.hprof进行转换。

  利用MAT打开转换后的 hprof文件:

  图2

  图3

  Histogram图表中主要统计了消耗占比较高的类的实例数量及占用空间

  Dorminator Tree(支配树)支配树可以直观地反映一个对象的retained heap

 1、Histogram查询

  用的最多的功能是 Histogram,点击 Actions下的 Histogram项将得到 Histogram结果,它按类名将所有的实例对象列出来,可以点击表头进行排序,在表的第一行可以输入正则表达式来匹配结果,我们一般查看Activity和Fragment是否有内存泄露,一般Fragmen会有混淆,所以需要QA保留好对应的mapping文件。

  图4

  2、选中占用内存最大的Activity->右键—>Merge Shortest Path To GC Roots->exclude allphantom/weak/soft etc. references

  Merge Shortest Path To GC Roots 它能够从当前内存映像中找到一条指定对象所在的到GC Root的最短路径。这个功能还附带了其他几个选项,这几个选项分别指明了计算最短路径的时候是否是需要排除弱引用、软引用及影子引用等,一般来说这三种类型的引用都不会是造成内存泄漏的原因,因为JVM迟早是会回收只存在这三种引用的资源的,所以在dump内存映像之前我们都会手动触发一次gc,同时在找最短引用路径的时候也会选择上exclude all phantom/weak/soft etc. references选项,排除来自这三种引用的干扰。

  3、结果如下图,由图可以看出 com.android.org.chromium.android_webview.Aw-

  PasswordHandler @0x42cbee10 组件始终调用com.baidu.next.tieba.reply.activity.

  ReplyDetailActivity @0x42bd52d8这个函数,导致内存泄漏问题。

  图5

卡顿

  卡顿产生的原因: 1、CPU 资源消耗原因;2、GPU 资源消耗原因。

  CPU上文已经阐述,接下来说一下GPU。一般安卓流畅度测试,关注图片处理器每秒刷新的帧数(FPS),他用来指示页面是否平滑的渲染。高的帧率可以得到更流畅,更逼真的动画,不过帧率达到60fps以上,人眼主观感受到的差别就不大了。所以以60fps作为衡量标准,即要求每一帧刷新的时间小于16ms,这样才能保证滑动中平滑的流畅度。

备注:GPU呈现模式用来测量app的帧速率,属于GPU,Profile工具的一种.目前安卓基础60fps以满帧数计算,60fps在一秒没绘制造成,所以可以计算出1÷60≈1.66(绘制每帧需要的时间约为16ms)

1、GPU呈现模式分析(Peofile GPU Rendering tool)

  测试方法:

  a、点击Android设备的“设置”->"开发者选项",然后勾选“GPU呈现模式分析”。

  b、打开开发者选项后勾选”GPU呈现模式分析”后选择“屏幕上显示为条形图”这样可以直观的看出每个时间点的帧数大小。如下图:

  图6

  当你的应用程序在运行时,你会看到一排柱状图在屏幕上,从左到右动态地显示,每一个垂直的柱状图代表一帧的渲染,越长的垂直柱状图表示这一帧需要渲染的时间越长.随着需要渲染的帧数越来越多,他们会堆积在一起,这样你就可以观察到这段时间帧率的变化。

 参数介绍如下:

  绿色水平线代表16ms,要确保一秒内打到60fps,你需要确保这些帧的每一条线都在绿色的16ms标记线之下.任何时候你看到一个竖线超过了绿色的标记现,你就会看到你的动画有卡顿现象产生.

  蓝色代表测量绘制的时间,或者说它代表需要多长时间去创建和更新你的DisplayList.在Android中,当你看到蓝色的线很高的时候,有可能是因为你的一堆视图突然变得无效了(即需要重新绘制),或者你的几个自定义视图的onDraw函数过于复杂.

  红色代表执行的时间,这部分是Android进行2D渲染 Display List的时间,为了绘制到屏幕上,Android需要使用OpenGl ES的API接口来绘制Display List.这些API有效地将数据发送到GPU,最总在屏幕上显示出来.

  橙色部分表示的是处理时间,或者说是CPU告诉GPU渲染一帧的时间,这是一个阻塞调用,因为CPU会一直等待GPU发出接到命令的回复,如果柱状图很高,那就意味着你给GPU太多的工作,太多的负责视图需要OpenGL命令去绘制和处理.

  c、如果需要分析具体详细的数据,需要结合下面的命令来进行,选择显示于adb shelldumpsys gfxinfo来使用,然后输入:adb shell dumpsys gfxinfo"你自己的应用名字" > fps.txt 后,在电脑中找到fps.txt文件,找到"Profile datain ms"的Draw Process Exceute这三列数据,Excel做出表格,sum出每列的总GPU时间,如图:

  图7-8

  Draw 对应于蓝色线:是消耗在构建java显示列表DisplayList的时间。说白了就是执行每一个View的onDraw方法,创建或者更新每一个View的DisplayList对象的时间。

  Process 对应于红色线:是消耗在Android的2D渲染器执行显示列表的时间。你的视图层次越多,要执行的绘图命令就越多。

  Execute 对应于橙色线:是消耗在排列每个发送过来的帧的顺序的时间.或者说是CPU告诉GPU渲染一帧的时间,这是一个阻塞调用,因为CPU会一直等待GPU发出接到命令的回复。

 2、FPS Meter测试安卓帧数

  FPSMeter是一款非常实用的小软件,能够用数字实时显示安卓界面的每秒帧数,非常直观。此外,FPS Meter还可以显示最大帧数、最小帧数以及平均帧数。由于涉及到了系统功能,所以FPSMeter需要root。如果你打算尝试,请先root机后再使用。开启服务后,即可看到有帧数显示于界面上。这里要注意,使用FPS Meter测量帧数需要在开发者选项中停用HW叠加层才会比较准确。

  3、在程序种画一个圆点,计算圆点1秒绘制次数

   贴吧目前记录FPS值的方法是,在程序中创建仅有一个圆点的view,然后计算该view每秒被绘制的次数。理想值:1秒绘制60次

  4、AndroidStudio 自带 GPU测功能

   如下图,AndroidStudio自带GPU监控功能,纵轴表示每桢绘制的时间,横轴是运行时间。

  图9

  上述四种方法就是测试FPS流畅度的常用方法。当QA发现有卡顿问题时,可以从以下几点着手分析,逐一排查。

  1、内存占用过多,GC次数高,阻塞主线程;

  2、主线程做了些无关的耗时操作,eg:在滑动过程中打日志,访问过多io;

  3、过度渲染,渲染层级太多或者次数太多,导致渲染时间长 eg:滑动过程中,动画导致整个列表重新绘制;

  4、创建view时,过多的动态创建或者复杂页面创建时间过长。eg:五楼图文直播轮播卡片。

0 人点赞