移动APP性能评测与优化
本文是《移动App性能评测与优化》的读书笔记。
PS:说是读书笔记,其实就是摘录。
移动App的性能测试主要包括:内存使用情况、电量消耗、功能的流畅度等;
1. 内存
1.1 内存的主要组成索引:
Native Heap : Native 代码分配的内存,虚拟机和Android框架本身也会分配;
Dalvik Heap : Java 代码分配的对象;
Dalvik Other : 类的数据结构和索引;
so mmap : Native 代码和常量;
dex mmap :Java 代码和常量;
1.2 内存测试工具
Android Studio / Memory Monitor : 观察 Dalvik 内存;
dumpsys meminfo : 观察整体内存;
smaps : 观察整体内存的详细组成;
MAT : 详细分析 Dalvik内存;
1.3 一个类的内存消耗
虚拟机在创建对象时的操作:
loadClass,将类信息从 dex 文件中加载进内存:
读取 .dexx mmap 中 class 对应的数据;
分配 native-heap 和 dalvik-heap 内存创建 class 对象;
分配 dalvik-LinearAlloc 存放 class 数据;
分配 delvik-aux-structure 存放 class 数据;
new instance 操作,创建对象实例
执行 .dex mmap 中 和 的代码;
分配 delvik-heap 创建 class对象实例;
dex mmap
在Android应用中的作用是映射classes.dex文件
1.4 dex 优化
省略掉dex的文件结构(自行查阅)
为了节省空间,dex将原先在 class 文件中重复的信息集中放置在一起,并以索引和指针的形式支持快速访问。
dex 文件中数据基本是按类名的字母顺序进行排列的,这样同样包名的类会排在一起,但程序实际执行时,同一个包下的类并不会全部调用到,而是跨包进行交互,但 mmap 加载了整个页面,可能会有很多无用的数据。
优化;
在APK的编译流程中,Proguard 混淆工具正好是能够对类名进行修改的,可以根据程序运行时的逻辑,将那些会互相调用的类改为为同一个 package 名,这样就可以使它们的数据排布在一起。
1.5 MAT(Memory Analyzer Tool)
使用MAT来分析应用的内存使用情况。通常在使用MAT打开hprof
文件后,能够在首页看到Top Comnsumers和 component Report等功能,我们可以快速定位一些大块的内存消耗。但我们在分析时会发现系统资源类占据了很大一部分内存,因此为去除这部分对分析的干扰,我们在使用AndroidSDK
提供的hprof-conv
转换时需要增加一个参数:
hporf- conv [-z] <infile><outfile> -z:exclude non-app heaps,such as Zygote
如果hprof文件是已经转换过的,则可以使用OQL:
//在数据中寻找应用的Application类对象,将对象地址转换为十进制后输入以下查询语句:
select * from instanceof java.langObject s where s.@objectAddress> 1107296256
//(后面那串数字应该是Application类对象的地址)
采用这两种方法后,再使用MAT来分析就可以比较容易发现自身代码的内存问题。
1.6 测试经验
MAT 是探索 Java 堆并发现问题和好帮手,能够迅速发现常见的图片和大数组等问题;
内存碎片问题一般隐藏在对象的地址中;
如需要测试非 Dalvik部分,有必要了解 Linux 的进程和内存原理、内存共享机制,熟悉常用命令行工具;
内存分配的最小单位是页面,通常为4KB,这个限制会引发各种问题;
1.7 性能优化
尽量不要在循环中创建很多临时变量;
可以将大型的循环拆散、分段或者按需执行;
引入SDK库和调用新的系统API里需要考虑成本;
除了Dalvik堆内存,还有其他类型的内存在了解了原理后也能够进行分析和优化;
dex 文件有很多优化空间。在仔细统计并调整了dex文件的顺序后,往往可以节约1M以上的 mmap 内存;
2. 耗电
在保证用户的必要体验前提下,尽可能减少不必要的操作。几个优化方法:
方法一:CPU时间片
当应用退到后台运行时,尽量减少应用的主动运行,当检测到CPU时间片消耗异常时,深入线程进行分析;
使用 DDMS 的 traceview 工具:获取进程运行过程中的 traceview,定位CPU占用率异常的方法。
方法二 wake lock
前台运行时运不要去注册 wake lock。 此时注册没有任何意义,却会被计算到应用电量消耗中。后台运行时,在保证业务需要的前提下,应尽量减少注册 wake lock;降低对系统的唤醒频率,使用 partial wake lock 代替 wake lock;
方法三 传感器
合理地设置 GPS 的使用时长和使用频率;
方法四 云省电策略
可考虑定期上报用户手机电量数据的方式来分析问题;
3. 流畅度
3.1 分析工具
hierarchy Viewer ,帮助我们去分析UI布局的情况;
Tracer for OpenGL ES,可以记录和分析APP每一帧的绘制过程,以及列出所有乃至的OpenGL ES 的绘制函数和耗时;该工具操作后会生成一份记录App绘制过程和gltrace文件,
Lint 扫描,发现代码中的流畅度性能问题;
Traceview,跟踪程序性能,具体到每一个函数的耗时和调用次数
Systrace ,获取App运行时线程的信息以及Api执行情况
< merge > 标签:用于减少View树的层次来优化 Android 的布局,通过该标签可以把 < merge > 标签里的UI合到上一层的 layout中。
< ViewStub> 标签,最大的优点是当你需要时才会加载,使用它并不会影响UI初始化时的性能。各种不常用的布局可以使用该标签来减少内存使用量,加快渲染速度。< ViewStub> 是一个不可见的,大小为0的View。
对于不常用的 UI 可以考虑使用 < ViewStub> 标签替代 GONE 来提高 UI 性能:
将 View 的可见性设置为 GONE,在 Inflate 布局时 View仍然会被 Inflate,也就是说仍然会创建对象,会被 实例化。而 ViewStud 是一个 轻量级的 View,它是一个看不见、不占布局位置、占用资源非常小的控件。
3.2 Perforjmance中的16个问题
DrawAllocation: 避免在绘制或者解析布局(draw/layout)时分配对象,比如在Ondraw()中实例化 Paint 对象;
Wakelock, 手机不能进入休眠状态,导致手机一直保持在高耗电状态;
Recycle :某些资源,比如 TypedArrays 、 VelocityTrackers,用完后应该被回收,但是忘记回收。
ObsoleteLayoutParam : Layout中无用的参数;
UseCompoundDrawables,可优化的布局;
HandlerLeak: Handler 的使用不当导致内存泄漏;
UseSparseArrays ,尽量用 Android 的SparseArray 代替 Hashmap;
UseValueOf : 需要常量对象时,不应该直接 new, 应该使用 ValueOf 转换。比如需要整数 42 的对象,不要直接用 new Integer(42),应该用 Intener.vallueOf(42),这样可以省内存;
DisableBaselineAlignment: 如果 LinearLayout 被用于嵌套 layout空间 计算,它的 android:baselineAligned 属性应该设置成 false ,以加速 layout 计算;
InefficientWeight : 当线性布局里只有一个控件,并且使用了weight 属性,最好把 weidth 和 height 设置为0,这样可以省略布局的 measure 过程;
FloatMath, 使用 FloatMath 代替 Math;
NestedWeights : 避免嵌套 weight ,那将拖累执行效率。
UnusedResources / UnusedIds, 未被使用的资源会使程序变大,并且编译速度降低;
Overdraw: 如果为 RootView 指定一个背景 Drawable,会先用Theme 的背景绘制一遍,然后才用指定的背景,这就是所谓的 “Overdraw” ,可以设置 theme 的background 为 null 来避免;
UselessLeaf / UselessParent : View 或 view 的父亲没有用,应该把它移除,避免影响加深布局的层次;
UnusedNamespace : 有些代码没必要使用 namespace ,会影响代码执行效率;
4. 网络优化
考虑点:
分小片传输一个文件(图片),这样当某一个分片失败时,只需要重传这一个分片就可以,而不用重传整个文件;
不同类型的移动互联网下的分片初始大小应该有所不同;
在上传一个文件的过程中,应当尽可能动态增大分片大小,以减小分片数量;
确定每个分片是否要继续增大之前,要检查网络类型是否发生了改变;
分片一旦传输失败,应当使用该网络下的初始分片大小进行重试;
重点优化优质网络下的传输速度,而不特意优化差网络下的速度;
5. apk瘦身
5.1 瘦身关键点:
代码部分:冗余代码、无用功能、代码混淆、方法数缩减;
资源部分:冗余资源、资源混淆、图片处理(压缩、图片转换、点9图化等);
对整个安装包做7zip极限压缩;
Android 系统安装一个应用的过程中,其中有一步是对 Dex 进行优化,优化的过程是使用专门的工具 DexOpt。DexOpt 是在第一次加载Dex文件的时候执行的。在DexOpt的过程会生成一个ODEX文件。
早期的 DexOpt 有两个问题:
DexOpt 会把每一个类的方法的id 检索起来,存在一个链表的结构里的,但是这个链表的长度是用一个 short 类型来保存的,导致了方法 id 的数目不能超过 65536(2^16);
DexOpt 使用 LinearAlloc 来存储应用的方法信息,LinearAlloc是一个固定大小的缓冲区(4,5,8,16),当方法数量过多也会导致超出缓冲区大小时,也会造成 DexOpt 崩溃;
5.2 缩减方法数的方法
避免在内部类中访问外部类的私有方法或变量;当在 java 内部类(包括 匿名内部类)中访问 外部类的私有方法或变量时,编译器会生成额外的方法;
避免调用派生类中的未被覆盖( override) 的方法;避免在派生类中调用未覆盖的基类的方法;避免用派生为对象调用派生类中未被覆盖的基类的方法。因为当调用派生类中的未被覆盖的方法时,会多产生一个方法数;
去掉部分类的get 、set 方法;
5.3 代码混淆
代码混淆( Obfuscated code)也叫花指令;对代码进行 Proguard 后,也可以比较大的减小代码的体积(即 dex 的体积);
6 参考文献:
移动APP性能评测与优化的更多相关文章
- 《移动App性能评测与优化》读书笔记
第一章:内存 内存的主要组成索引: Native Heap:Native代码分配的内存,虚拟机和Android框架本身也会分配 Dalvik Heap:Java代码分配的对象 Dalvik Oth ...
- 移动App性能评测与优化-Android内存测试 ,DVM原理
常见的测试方法包括Monkey/UIAutomator类的常规压力测试,大数据/操作的峰值压力测试,长时间运行的稳定性测试等. 前提: 测试准备:版本是纯净版本,不应该附加多余的log和调试用组件. ...
- Android App性能评测分析-流畅度篇
1.前言 在手机App竞争越来越激烈的今天,Android App的各项性能特别是流畅度不如IOS,安卓基于java虚拟机运行,触控响应的延迟和卡顿比IOS系统严重得多.一些下拉上滑.双指缩放快速打字 ...
- Android App 性能评测与调优
要点: 1. 内存优化的目的以及工具介绍 2. Android APP 内存的主要问题分析与总结 3. UI 绘制原理以及量化工具 - UI 流畅度的主要问题分析以及 UI 绘制原理. 4. 如何获取 ...
- 移动App性能测评与优化1.4.4 多进程应用
1.4.4 多进程应用 根据上一节中的描述,当一个进程结束后,它所占用的共享库内存将会被其他仍然使用该共享库的进程所分担,共享库消耗的物理内存并不会减少.实际上,对于所有共享使用了这个库的应用,Pss ...
- Android APP性能分析方法及工具
近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借 ...
- android app性能优化大汇总(UI渲染性能优化)
UI性能测试 性能优化都需要有一个目标,UI的性能优化也是一样.你可能会觉得“我的app加载很快”很重要,但我们还需要了解终端用户的期望,是否可以去量化这些期望呢?我们可以从人机交互心理学的角度来考虑 ...
- fir.im Weekly - 如何进行 Android App 性能优化
关于 Android App 的优化,@anly-jun 用 3 个月完成了这一系列文章,从 性能分析工具 到 ANR .Layout .消除卡顿 到 内存优化.内存分析工具大概十五六篇,并对此做一个 ...
- iOS app性能优化的那些事
iPhone上面的应用一直都是以流畅的操作体验而著称,但是由于之前开发人员把注意力更多的放在开发功能上面,比较少去考虑性能的问题,可能这其中涉及到objective-c,c++跟lua,优化起来相对 ...
随机推荐
- 制作qq简易聊天框
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- (趣味哈哈镜)JMF中摄像头相关的问题
JMF已经非常古老了.最近由于做实验的需要,不得不使用JMF处理视频.开发使用win10系统和eclipse.使用中的问题如下: 1.首先想要使用JMF需要必须安装32位JDK,同时编译软件也需要是3 ...
- 4.设置静态IP
由于Ubuntu重启之后,ip很容易改变,可以用以下方式固定ip地址 1.设置ip地址 vi /etc/network/interface # The loopback network interfa ...
- linux 强制重启!
原文链接:https://www.cnblogs.com/wipy/p/4261472.html 有时候,linux 由于硬盘或者其它原因, 某个进程挂住了,怎么也杀不死, 输入 reboot 命令也 ...
- Java 类初始化和实例初始化过程
1.类初始化过程 2.实例初始化过程 3.方法的重写
- 团队作业1——团队展示&选题 (追忆少年)
目录 一,团队展示 1.1队名 1.2队员学号 1.3项目描述 1.4队员风采 1.5团队分工 1.6团队合照 1.7团队特色 (一)目标导向 (二)协作基础 (三)共同的规范和方法 (四)技术或技能 ...
- 团队作业4:第三篇Scrum冲刺博客(歪瑞古德小队)
目录 一.Daily Scrum Meeting 1.1 会议照片 1.2 项目进展 二.项目燃尽图 三.签入记录 3.1 代码/文档签入记录 3.2 Code Review 记录 3.3 issue ...
- 如何简洁优雅地部署PostgreSQL和Pgweb?
本文转自Rancher Labs 介绍PostgreSQL和Pgweb PostgreSQL是一款以可靠性和性能为人所熟知的开源数据库.它在很多行业和应用程序中都有应用,尤其是web开发人员的最爱.从 ...
- 洛谷 P3951 NOIP 2017 小凯的疑惑
洛谷 P3951 NOIP 2017 小凯的疑惑 题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付 ...
- 2、Entity Framework Core 3.1入门教程-创建数据库和迁移
本文章是根据 微软MVP solenovex(杨旭)老师的视频教程编写而来,再加上自己的一些理解. 视频教程地址:https://www.bilibili.com/video/BV1xa4y1v7rR ...