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

本文涉及的产品
性能测试 PTS,5000VUM额度
简介: 本文详细介绍了Android应用性能测试中的内存泄漏与卡顿问题及其解决方案。首先,文章描述了使用MAT工具定位内存泄漏的具体步骤,并通过实例展示了如何分析Histogram图表和Dominator Tree。接着,针对卡顿问题,文章探讨了其产生原因,并提供了多种测试方法,包括GPU呈现模式分析、FPS Meter软件测试、绘制圆点计数法及Android Studio自带的GPU监控功能。最后,文章给出了排查卡顿问题的四个方向,帮助开发者优化应用性能。

来源: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:五楼图文直播轮播卡片。

相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
目录
相关文章
|
2月前
|
存储 前端开发 Java
Android MVVM架构模式下如何避免内存泄漏
Android采用MVVM架构开发项目,如何避免内存泄漏风险?怎样避免内存泄漏?
99 1
|
20天前
|
Android开发 开发者
Android性能优化——内存管理的艺术
Android性能优化——内存管理的艺术
|
2月前
|
编解码 Android开发 UED
构建高效Android应用:从内存优化到用户体验
【10月更文挑战第11天】本文探讨了如何通过内存优化和用户体验改进来构建高效的Android应用。介绍了使用弱引用来减少内存占用、懒加载资源以降低启动时内存消耗、利用Kotlin协程进行异步处理以保持UI流畅,以及采用响应式设计适配不同屏幕尺寸等具体技术手段。
51 2
|
3月前
|
缓存 Java 测试技术
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
使用JMeter对项目各个接口进行压力测试,并对前端进行动静分离优化,优化三级分类查询接口的性能
101 10
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
|
2月前
|
网络协议 Ubuntu 前端开发
好好的容器突然起不来,经定位是容器内无法访问外网了?测试又说没改网络配置,该如何定位网络问题
本文记录了一次解决前端应用集成到主应用后出现502错误的问题。通过与测试人员的沟通,最终发现是DNS配置问题导致的。文章详细描述了问题的背景、沟通过程、解决方案,并总结了相关知识点和经验教训,帮助读者学习如何分析和定位网络问题。
105 0
|
3月前
|
测试技术 Shell Android开发
Android 性能测试初探 (六)
本节聊聊性能测试的最后一项- 流量,当然我所指的性能测试是针对大部分应用而言的,可能还有部分应用会关注网速、弱网之类的测试,但本系列文章都不去一一探讨了。
56 6
|
3月前
|
JavaScript 测试技术 Android开发
Android 性能测试初探 (四)
本文介绍了GPU在移动端性能测试中的重要性,并详细解释了过度绘制、帧率和帧方差的概念。针对GPU测试,文章列举了三项主要测试内容:界面过度绘制、屏幕滑动帧速率和平滑度。其中,过度绘制测试需遵循特定标准,而帧速率和平滑度测试则可通过软件或硬件方法实现。在软件测试中,使用Systrace插件和高速相机是两种常用手段。对于不同机型,帧率及帧方差的测试标准也需相应调整。
56 5
|
3月前
|
测试技术 Shell Android开发
Android 性能测试初探 (三)
本文承接《Android性能测试初探(二)》,深入探讨CPU与内存测试。介绍了移动端内存测试的重要性及其测试目标,并详细列举了不同状态下应用内存消耗情况的测试项目。此外,还提供了多种内存测试方法,包括使用`procrank`等工具的具体操作步骤。最后,文章也简要提及了CPU测试的相关内容,帮助读者更好地理解Android性能测试的关键要素。
54 5
|
3月前
|
测试技术 Shell 定位技术
Android 性能测试初探 (五)
聊聊大家不常关注的测试项- 功耗
55 3
|
3月前
|
算法 测试技术 Android开发
Android 性能测试初探 (二)
上回大体介绍了下在 android 端的性能测试项,现在我们就细节测试项做一些阐述(包括如何自己 DIY 测试)
48 4