Android基础性能检测与分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/KevinDGK/article/details/53257601

本文内容:基于Android基础性能检测与分析

版权声明:本文为原创文章,未经允许不得转载

博客地址:http://blog.csdn.net/kevindgk

前言

最近一段时间以来,开始深入学习App的性能检测、分析和优化等方面的内容,接触的越多越发现相关的技能点太多了,而且说起来容易做起来难。尤其是学习到持续自动化框架的方案和搭建,才觉得自己了解的不过是冰山一角。只能说,学无止境,任重而道远!

不过,在学习的过程中,发现了很多非常实用的技巧以及很棒的性能优化和检测工具,能够帮助自己及时发现程序的一些问题,比如UI界面的性能、启动时间的优化、OOM异常、内存泄露、电量分析等,并且对自己的软件的整体性能有一个综合的分析。

本文主要的研究方向都是来自与《Android 群英传 之神兵利器》,只不过小编整理了内部较为实用的内容,然后深入研究了一下。

GO!GO!GO!

1.UI性能分析

目标:减少绘图和显示数据的等待时间,使帧率更加平稳、连贯,给人更好的视觉体验。

  • 16msUI绘制准则

一般来说,Android设备的屏幕刷新率为60帧/s,要保持画面流畅不卡顿,要求每一帧的时间超过1000/60=16.6ms,这就是16ms的黄金准则,如果中间的某些帧的渲染时间超过16ms,就会导致这段时间的画面发生了跳帧,因此原本流畅的画面变发生了卡顿。

在Android 5.0之后,系统增加了Render Thread(渲染线程),来进行异步绘制,即使某一帧发生延迟也不会影响下一帧的绘制。

在手机的开发者选项中打开Pofile GPU Rending(剖析GPU渲染)选项,就可以看到底部的柱状图,表示的就是渲染的时间。一条绿色的横线表示的就是16ms(17ms)基准线,如果高于该线,就表示人眼会觉得绘制的不流畅。通过这种方式,就可以数据化的分析界面的流畅度,然后再逐步找到问题所在,优化我们的界面。

在Android Studio中,Android Monitor->Monitors->GPU界面也可以看到该信息,但是要求安装AS插件,并且要求向手机安装追踪GPU渲染数据的应用,要求手机有root权限才可以。

  • 布局

如果使用LinearLayout,则一定要保证层级不能太深,google官方建议用户界面的View不宜超过8层;

如果使用RelativeLayout,则一定要尽量避免嵌套,因为相对布局在测量的时候往往需要多次测量,嵌套时十分耗时。

eg:可以使用include标签进行view的复用;使用drawableleft方法来进行控件组合。

最根本的还是尽量减少View的数量。

  • 图形过度绘制

如果控件出现了叠加,而且都有背景,就会造成重叠部分多次绘制,浪费了资源和时间。可以打开开发者选项中的Debug GPU Overdraw,可以检测过渡绘制,即一块区域经过了几次叠加绘制:

​ 原色:没有过度绘制

​ 蓝色:1次过度绘制

​ 绿色:2次过度绘制

​ 粉色:3次过度绘制

​ 红色:>=4次过度绘制

修改建议:

①控件尽量避免重叠摆放;

②当控件与主背景色颜色相同时,移除不需要背景色;

③自定义view在绘制的时候,使用clipRect属性减少重绘区域。

2.应用启动时间计算以及程序启动白屏问题

这里的应用启动时间指的是,安装完应用以后的第一次启动,这也是评判一个App性能好坏的重要指标,直接影响用户的对应用的第一印象。

可以通过ADB命令来统计应用从打开到开启第一个界面的时间:

adb shell am start -W com.dgk.test/.login.SplashActivity

该命令是用Activity Manager去开启界面,然后统计时间,最终终端会打印时间:

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.dgk.test/.login.SplashActivity }
Status: ok
Activity: com.dgk.test/.login.SplashActivity
ThisTime: 1212  // 最后一个启动的Activity的启动耗时
TotalTime: 1212 // 自己的所有Activity的启动耗时
WaitTime: 1219  // AMS启动App的Activity的总时间,包含当前Activity的onPause()和自己Activty的启动
Complete

如果第二次启动你会发现,基本上也就在200-500ms之间。

注意:如果是debug版本,第一次启动的时间会有很长时间的白屏,有时候能达到10s左右。这个是因为为了要让Instant Run功能可以正常工作,程序首次安装的时候需要做非常多的初始化工作,使得后期开发效率增大。所以说,这个是正常的,因为在release版本就没有这个情况了。最好不要直接禁用掉该功能,毕竟调试阶段以开发为主,利大于弊。

3.内存分析

内存优化原则

①在对象不需要的时候确保能够及时回收;

②尽量复用需要多次使用的对象;

内存区分

  • 寄存器 Registers:用于存储指令、地址、数据;
  • 栈Stack:存放基本类型的数据、对象的应用和函数地址等,系统控制,使用完毕后由虚拟机释放该变量占用的空间;
  • 堆Heap:存放对象本身和数组,开发者创建,生命周期结束后由GC回收;
  • 静态域static field:存储静态变量;
  • 常量池constant pool:存储常量。

内存分析

adb shell getprop|findstr dalvik.vm

可以查看到手机能够给App分配的实际物理内存大小,这些数值跟手机相关,都是定义在系统的ROM中的系统属性,在编译的时候就已经写入了系统:

  • dalvik.vm.heapgrowthlimit 256m // 单个App的分配物理内存最大值为256MB
  • dalvik.vm.heapsize 512m // 单个App申请了large heap后的最大值为512MB

  • 虚拟机内存:可以通过上面提到过的adb shell dumpsys meminfo 包名 来获取时时的内存信息,但是Android Studio已经在Android Monitor中的Monitors中查看Memory窗口中查看内存的波动信息,该内存指的是Heap Alloc,即分配的虚拟机堆内存大小,我的测试程序在25-30M浮动,如果开多线程或者调用扫描二维码,会达到近40M。

该功能被集成在了Android Studio中:

当连接上ADB,有进程在监听的时候,点击途中的图标就可以看到内存信息:

重点关注一下图中加了注释的和圈起来的数据就可以了,很直白的就可以看到该程序:

实际分配的内存:78682KB = 76.8MB
虚拟机分配的内存:26328KB = 25.6MB,已经分配出去使用了23733KB = 23.2MB,使用率为90%
内存中的类:
    Activity:0
    APPContexts:2
    。。。
数据库:0

当程序一直运行的时候,这个数据会不断的变化,如果想要仅仅简单的看一下虚拟机的内存,可以从AS的Monitors里看,如果想要看详细的信息,可以不断的执行下面的命令来不断的更新内存状态

adb shell dumpsys meminfo 包名

在这个过程中,重点关注一下PSS Total,物理内存总大小,以及各个对象的数量。

分析场景1

让App界面多次开启和关闭,查看Views和Activities的数量是否在退出后变回开启前的数量,比如在测试的时候,第一次进入程序SplashActivity->MainActivity,由于SplashActivity finish了,这个时候应该显示只有1个界面。此时,我打开了一个WebViewActivity,然后又关掉了,这个时候界面仍然显示2个界面。所以我不断的打开和关闭H5界面,发现内存增长的特别快,很快就到了150MB,按照这个速度,100下估计就能达到该手机的应用可分配的最大阈值256MB了。

于是,问题来了,说明WebViewActivity并没有被销毁掉,往往第一反应就是发生了内存泄露。查看了一下代码,由于H5和Android有很多次业务交互,在JSObject中持有了WebViewActivity的引用,当Activity onDestroy的时候,仅仅是销毁了视图而已,内存并没有回收。所以我将WebViewActivity传递为Context,然后测试了一下,发现是可以正常回收的,但是我还需要调用Activity的逻辑,所以就使用了大量的接口。虽然稍微麻烦了一些,但是解决了内存泄露的问题。

分析场景2:

那么,如果获取更多的内存,避免程序OOM异常呢?

①开多进程:因为每个进程都会分配一块内存,加起来就很多,但是也会造成更多的系统开销和跨进程沟通问题;

②使用本地堆内存:Android系统限制的是Java Heap的大小,而Native Heap的内存分配是由系统分配的不受限制,所以可以通过jni来申请分配heap。例如Fresco就是通过在Native Heap上进行内存分配来减少使用虚拟机内存,从而避免因图像占用内存过大而造成的OOM异常;

③使用OpenGL

④申请LargeHeap:在清单文件中设置LargeHeap参数来给App分配更多的内存,但是也会增加了GC的难度,所以有利也有弊。

内存泄露工具:MAT

Eclipse的一个插件,也可以单独来使用,十分强大。

内存泄露工具:LeakCanary

Square的杰作,使用十分方便,gitlab地址为:LeakCanary

4.耗电量分析

手机”设置”->电量和性能,可以看到整个电池的使用情况,点击应用,可以看到内部的一个功耗分析。运行一段时间应用以后,我们可以对App的耗电情况有一个初步的判断,然后再利用工具进行详细的分析,具体看下文。

5.性能检测和分析工具

5.1 高通性能分析器 - TrepnProfiler

高通开发的一款性能分析工具,可以用于测试手机系统以及App的性能参数,主界面:

从图中可以看出,该软件具有的功能:

  • 分析系统(手机)

  • 分析App(应用)

  • 分析运行

  • 设置

    一般配置:模式、显示信息、分析间隔、保存和加载数据等

    数据点:需要采集的数据信息,一般不要超过6个,否则会影响到应用的性能

    覆盖图:显示浮层窗口数据,这些图标可以高度自定义

我们重点关注的就是分析App和设置选项,点击分析App:

停止分析,还可以输出详细信息:

注:.csv文件可以用Excel打开。

5.2 高通调试器 - TuneUpKit

App Tune-up Kit 为开发人员提供了一种创新方法,能够在短短60秒内分析任何Android应用。手指轻点,您就可以从五大关键方面评估应用性能:CPU、GPU、功耗、发热量及移动网络数据。

特性:

  • 一键分析Android应用
  • 从5大关键方面评估性能:CPU、GPU、功耗、发热量及网络数据
  • 用通俗易懂、按颜色区分的分析面板展现结果
  • 功耗估算——在不能直接读取电量时,自动估算实时功耗
  • 应用自动评级(为获得更好准确性,评级基于处理器)
  • 自动比较任意Android应用在Google Play同类热门应用中的表现*
  • 评定应用在Google Play前20名应用或某个类别如游戏类最受欢迎应用中的表现

5.3 阿里-易测

易测是阿里移动质量中心基于研发自持机上提供的客户端测试解决方案。

官方地址

优点:可以一键测试很多性能,报告比较全面;

缺点:很多功能需要手机root权限,部分性能测试需要上传apk,并且需要排队很久才返回测试报告。

6.云测平台

随着性能测试、兼容性测试的需求日益增加,越来越多测厂商开始推广云测试平台,比如:

这些云测试平台大同小异,与Google的Cloud Test Lab功能基本相同,包含:

a.兼容性测试:通过大量真机覆盖大部分机型

b.压力测试:通过脚本实现压力测试

c.缺陷分析:通过代码静态扫描和测试中发生的ANR、Crash等提供应用的缺陷分析

d.性能测试:在测试中监控应用性能等数据

e.远程真机租用:用户可以远程访问DeviceLab中的真机,并通过远程控制的方式进行使用。

使用云测平台在一定程度上解决了很多公司的测试问题,特别是一些付费的服务,可以进行一些”深度测试和分析”,让公司享受到更好的测试服务。例如可以帮助测试人员进行分析、录制脚本和回放等功能,对于一些初创企业来说,目前算是一种比较好的测试与优化手段。

引用

1.《Android 群英传 之 神兵利器》 徐宜生

2.https://developer.android.com/studio/intro/index.html?hl=zh-cn

3.http://pkaq.org/gradledoc/docs/userguide/userguide.html

联系方式

邮箱:[email protected]

微信:

猜你喜欢

转载自blog.csdn.net/KevinDGK/article/details/53257601
今日推荐