Android性能优化篇之内存优化--内存优化分析工具

image

引言

1. Android性能优化篇之内存优化--内存泄漏

2.Android性能优化篇之内存优化--内存优化分析工具

3.Android性能优化篇之UI渲染性能优化

4.Android性能优化篇之计算性能优化

5.Android性能优化篇之电量优化(1)——电量消耗分析

6.Android性能优化篇之电量优化(2)

7.Android性能优化篇之网络优化

8.Android性能优化篇之Bitmap优化

9.Android性能优化篇之图片压缩优化

10.Android性能优化篇之多线程并发优化

11.Android性能优化篇之数据传输效率优化

12.Android性能优化篇之程序启动时间性能优化

13.Android性能优化篇之安装包性能优化

14.Android性能优化篇之服务优化

介绍

上一章讲了内存相关的知识和内存泄漏的常见案例以及解决方法,我们写代码的时候要注意避免。但是我们不可能完全避免出现内存泄漏的情况,所以就要通过内存分析工具来分析是否产生了内存泄漏。主要讲的工具有以下几种:

Heap Snapshot
Heap Viewer
MAT
Allaction Tracking
TraceView
LeakCanary
Lint


下面我们就来一一讲解这些工具的使用:

1.Heap Snapshot

Heap Snapshot 是 android Studio 中 Android Monitor中的一个分析Java堆内存信息的工具,这边我们就用上章中的单例导致内存泄漏的例子来分析:

(1).Heap Dump启动

点击图中红色框中的Dump Java Heap,就会dump 出java堆内存信息文件(.hprof)


image1.png
(2).分析Heap Snapshot面板中的信息

android studio会自动打开hprof文件,我们这时候就可以来重点分析我们需要检查的类是否有内存泄漏(必须要确定分析具体的类,比如我们分析MainActivity是否有内存泄漏,可以反复的改变屏幕的方向,然后dump出堆信息)


image2.png

我们看到ClassName中可能数据太多,我们怎么能够定位到我们要分析的类呢,可以选择第二个红色框中的选择项来快的定位。


image4.png

我们选择通过包来展示,这样可以通过包名来快速定位。
image5.png

下面我们来分析下MainActivity是否有内存泄漏。


image6.png

我们看到这里MainActivity有两个实例且都有深度,也就是说都被引用,根据Acitivity的生命周期原理,屏幕的旋转会回收之前的Activity,然后创建一个新的Activity,另一个一个被回收或者等待被回收,所以MainActivity肯定存在内存泄漏的问题。这个需要结合下面的引用树来看,但是这个太麻烦还不要用对,下面我们将介绍更好的工具来分析,这边只要知道我们分析的类是否发生内存泄漏就行了。


下面我们给出Snapshot中表中字段含意:

Class Name 板块
    Total Count     内存中该类的对象个数
    Heap Count      堆内存中该类的对象个数
    Sizeof          物理大小
    Shallow size    该对象本身占有内存大小
    Retained Size   释放该对象后,节省的内存大小

Instance 板块

    depth           深度
    Shallow Size    对象本身内存大小
    Dominating Size 管辖的内存大小


2.Heap Viewer

Heap Viewer 是 Android Device Monitor 中的实时查看App分配的内存大小和空闲内存大小和发现内存泄漏的工具。
使用条件:1.必须5.0以及以上的系统,2.开发者选项可用

使用步骤:
    1.打开Android Device Monitor 
    2.点击DDMS
    3.选中heap选项卡
    4.选中我们的项目
    5.点击update heap
    6.点击Cause GC
image7.png
下面解释下Heap面板中表示的意思:
image8.png

A

    Heap Size   堆栈分配给App的内存大小
    Allocated   已分配使用的内存大小
    Free    空闲的内存大小
    %Used   Allocated/Heap Size,使用率
    Objects 对象数量

B 中 Type 类型

    free    空闲的对象
    data object 数据对象,类类型对象,最主要的观察对象
    class object    类类型的引用对象
    1-byte array(byte[],boolean[])  一个字节的数组对象
    2-byte array(short[],char[])    两个字节的数组对象
    4-byte array(long[],double[])   4个字节的数组对象
    non-Java object 非Java对象

B 中 表中列的表示意思

    Count   数量
    Total Size  总共占用的内存大小
    Smallest    将对象占用内存的大小从小往大排,排在第一个的对象占用内存大小
    Largest 将对象占用内存的大小从小往大排,排在最后一个的对象占用的内存大小
    Median  将对象占用内存的大小从小往大排,拍在中间的对象占用的内存大小
    Average 平均值

当我们点击某一行时,可以看到 C 的柱状图 ,表示 横坐标是对象的内存大小,这些值随着不同对象是不同的,纵坐标是在某个内存大小上的对象的数量

下面我们来发现有内存泄漏的单例例子:
(1).旋转屏幕前,我们看到已经分配的内存为814.617kb(手动GC):


image9.png

(2).旋转屏幕后,我们看到已经分配的内存为956.891kb(手动GC):


image10.png

我们对比前后的两次发现有内存不能被回收,也就是说旋转屏幕导致内存泄漏了。这个工具没法具体定位到内存泄漏的位置。

补充:Heap Viewer不光可以用来检测是否有内存泄漏,对于内存抖动,我们也可以用该工具检测,因为内存抖动的时候,会频繁发生GC,这个时候我们只需要开启Heap Viewer,观察数据的变化,如果发生内存抖动,会观察到数据在段时间内频繁更新


3.MAT

全称为Memory Analyzer Tool,一款详细分析Java堆内存的工具,该工具非常强大,为了使用该工具,我们需要hprof文件。但是该文件不能直接被MAT使用,需要进行一步转化,可以使用hprof-conv命令来转化,但是Android Studio可以直接转化.

下面我们就来那Heap Snapshot 中的hprof来分析:

(1).转换hprof文件


image11.png

(2).使用Memory Analyzer Tool工具打开hprof文件


image12.png

工具会自动生成一个可疑的内存泄漏,其实这里对我们用处不大,我们主要分析overView选项卡。


image13.png

我们看到这里给出了一些基本的数据我大对象的图,我们主要分析下面的Actions中的三个工具:
Histogram

主要是列出每个类中对象,点击看下:


image14.png

我们看到这边的对象有点多,我们选择按照包来显示,或者通过regex来筛选。
image15.png

找到我们要分析的类,选择ListObject中的with incoming references,来显示引用MainActivity的类。
image16.png

我们看到这边有两个地方引用了MainActivity,然后现在图中的选项,排除所有的soft,weak,phantom引用,看看当前的被什么引用。我们来看下两个结果:

image17.png
image18.png

我们看到一个被CommonUtil引用,导致内存泄漏,一个被InputMethodManger引用,导致内存泄漏,第二个是系统输入法的bug,而第一个是我们自己写的,如果列表中显示很多我们只能一一分析。

上面是分析一个hprof来看,可能有时也看不出来,那么我们可以通过两个hprof来对比分析。

对比分析

(1).将两个hprof文件添加到工具中
(2).将两个hprof文件添加到对比列表中


image19.png

(3).对比分析


image20.png
image21.png

我们看到经过旋转操作,MainActivity有两个,所以这边肯定发生了内存泄漏,那到底是什么引起内存泄漏的呢?下面的分析步骤就和上面单独分析一个hprof文件一样了。

4.Allaction Tracking

Allocation Tracker(AS)工具比Allocation Tracker(Eclipse)工具强大的地方是更炫酷,更清晰,但是能做的事情都是一样的。所以我们就分析Android Studio中的。

(1).Allocation Tracker启动,生成alloc文件
image22.png
(2).分析alloc文件
image23.png

这边有两种显示的方式:
*Group by Method:用方法来分类我们的内存分配
*Group by Allocator:用内存分配器来分类我们的内存分配
首先以线程对象分类,默认以分配顺序来排序,当然你可以更改,只需在Size上点击一下就会倒序,如果以Count排序也是一样,Size就是内存大小,Count就是分配了多少次内存,点击一下线程就会查看每个线程里所有分配内存的方法

当你以Group by Allocator来查看内存分配的情况时,详细信息区域就会变成如下


image24.png

这种方式显示的好处,是我们很好的定位我们自己的代码的分析信息


分类旁边还有跳转到源码的位置和统计图。
轮胎图

image25.png

轮胎图是以圆心为起点,最外层是其内存实际分配的对象,每一个同心圆可能被分割成多个部分,代表了其不同的子孙,每一个同心圆代表他的一个后代,每个分割的部分代表了某一带人有多人,你双击某个同心圆中某个分割的部分,会变成以你点击的那一代为圆心再向外展开。如果想回到原始状态,双击圆心就可以了。

柱状图
柱状图以左边为起始点,从左到右的顺序是某个的堆栈信息顺序,纵坐标上的宽度是以其Count/Size的大小决定的。柱状图的内容其实和轮胎图没什么特别的地方


image26.png

5.TraceView

从代码层面分析性能问题,针对每个方法来分析,比如当我们发现我们的应用出现卡顿的时候,我们可以来分析出现卡顿时在方法的调用上有没有很耗时的操作.
主要是下面两个问题:

  • 调用次数不多,但是每一次执行都很耗时
  • 方法耗时不大,但是调用次数太多

简单一点来说就是我们能找到频繁被调用的方法,也能找到执行非常耗时的方法,前者可能会造成Cpu频繁调用,手机发烫的问题,后者就是卡顿的问题.

(1).打开Android device monitor,选中我们的应用,点击start method profiling,开始trace
image30.png
(2).操作我们的应用,再次点击上面的按钮,生成trace文件
image31.png

traceview的面板分上下两个部分:
*时间线面板以每个线程为一行,右边是该线程在整个过程中方法执行的情况
*分析面板是以表格的形式展示所有线程的方法的各项指标

时间线面板
左边是线程信息,main线程就是Android应用的主线程,这个线程是都会有的,其他的线程可能因操作不同而发生改变.每个线程的右边对应的是该线程中每个方法的执行信息,左边为第一个方法执行开始,最右边为最后一个方法执行结束,其中的每一个小立柱就代表一次方法的调用,你可以把鼠标放到立柱上,就会显示该方法调用的详细信息,你可以随意滑动你的鼠标,滑倒哪里,左上角就会显示该方法调用的信息。

分析面板
面板列名含义:

    Name    方法的详细信息,包括包名和参数信息
    Incl Cpu Time   Cpu执行该方法该方法及其子方法所花费的时间
    Incl Cpu Time % Cpu执行该方法该方法及其子方法所花费占Cpu总执行时间的百分比
    Excl Cpu Time   Cpu执行该方法所话费的时间
    Excl Cpu Time % Cpu执行该方法所话费的时间占Cpu总时间的百分比
    Incl Real Time  该方法及其子方法执行所话费的实际时间,从执行该方法到结束一共花了多少时间
    Incl Real Time %    上述时间占总的运行时间的百分比
    Excl Real Time %    该方法自身的实际允许时间
    Excl Real Time  上述时间占总的允许时间的百分比
    Calls+Recur 调用次数+递归次数,只在方法中显示,在子展开后的父类和子类方法这一栏被下面的数据代替
    Calls/Total 调用次数和总次数的占比
    Cpu Time/Call   Cpu执行时间和调用次数的百分比,代表该函数消耗cpu的平均时间
    Real Time/Call  实际时间于调用次数的百分比,该表该函数平均执行时间

6.LeakCanary

quare公司开发的可以直接在手机端查看内存泄露的工具
实现原理:本质上还是用命令控制生成hprof文件分析检查内存泄露。
GitHub:https://github.com/square/leakcanary

使用:

(1).添加如下依赖
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
(2).添加Application子类

首先创建一个ExampleApplication,该类继承于Application,在该类的onCreate方法中添加如下代码开启LeakCanary监控:

    LeakCanary.install(this);

具体的就不在说了,网上有很多,使用起来先对比较简单。

7.Lint

android stidio 自带的工具,功能很强大。
主要功能:

  • 检测资源文件是否有没有用到的资源。
  • 检测常见内存泄露
  • 安全问题SDK版本安全问题
  • 是否有没有使用的代码
  • 代码的规范
  • 自动生成的罗列出来
  • 提示去除没用的导包
  • 提示可能的bug
image27.png

点击inpsect code,工具就会自动分析你的项目代码。


image28.png

(1). correctness 有错误的代码
(2). performance 性能方面
(3). security 安全方面,常见的是备份
(4). usability 应该使用的方式
(5).class structure 类结构问题
(6). control flow issues 控制流程问题
(7). declaration redundancy 声明冗余
(8). imports 提示去除没用的导包
(9). probable bugs 可能的bug
(10). spelling 代码的规范,驼峰命名法等

我们主要看下内存泄漏有没有提示:


image29.png

我们看到这里直接提示我们可能出现的内存泄漏,很强大呀!

补充:在打包发布时,可以用Lint工具来去除多余的没有使用的资源和类,来减小apk的体积。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 每个人都有自己的秘密 秘密使人变的神秘 秘密使人变的更加谨慎 秘密使人变的更加努力 秘密使人变的更加强大 秘密使生...
    淡淡27阅读 183评论 0 0
  • 1986年青岛作为五个城市之一,列为单列经济城市。什么叫单列呢?就是这类城市由中央来管辖师傅,是副省级的单位。 这...
    RGLR阅读 245评论 0 0
  • DVWA-1.9系列一共分为10个功能模块: Brute Force(暴力破解) Command Injectio...
    网络安全自修室阅读 1,293评论 0 0
  • 如果你从这篇文章中看到了你的影子,别太在意,我不是在写你,但又有可能在写你。 天暗了下来,是回家的时间了,我特意没...
    解忧少年阅读 490评论 11 7
  • 从前,一直听身边的同事在不同的场景中说,要学会换位思考。 给他人留有印象之时,也不是谈起,要学会换位思考。 前段时...
    夏日嬷嬷茶1008阅读 1,020评论 0 0