当前位置:
文档之家› Android性能优化和提高
Android性能优化和提高
Android 优化和性能提高
主讲 : 林广彬 QQ :646336082
目录
概览 原因 从设计开始做起 和普通 Java 理念不同 常用优化要点 本地代码指令 执行不同指令所需时间的对比
为什么我们要关心性能
摩尔定律
摩尔定律不适用移动设备
手机越来越小 功耗会越来越低 电池的持续的时间越来越长
嵌入式处理器通常没有支持浮点运算的硬件 可能会通过软件实现的
解决之道
用整数 或 fixed-整数
性能的测试数据
Action Add a local variable Add a member variable Call String.length() Call empty static native method Call empty static method Call empty virtual method Call empty interface method Call Iterator:next() on a HashMap Call put() on a HashMap Inflate 1 View from XML Inflate 1 LinearLayout containing 1 TextView Inflate 1 LinearLayout containing 6 View objects Inflate 1 LinearLayout containing 6 TextView objects Launch an empty activity
用静态方法比虚方法好
static method ….
否则需要一个虚函数表 体现出这个函数的调用不会改变对象的状态
仅适用于不需要访问一个对象的成员变量 时
移动应用中的特殊代码级优化
似乎和你以前在学校和经验中的Java知识 有些矛盾 Android移动环境有其特殊性。 以前的 Java 环境是台式电脑和服务器上的 编程经验
创建含有SD 卡的 AVD
复制跟踪文件到主机
系统会创建跟踪文件<trace-base-name> 使用adb来复制文件 adb pull /sdcard/calc.trace /tmp
Traceview中查看跟踪文件
输入traceview <trace-base-name> 加载跟踪日志文件并显示在一个窗口中
避免ANR的方法
什么引发了ANR 在5秒内没有响应输入的事件(例 如,按键按下,屏幕触摸) BroadcastReceiver在10秒内没有 执行完毕 避免ANR的方法
Android 程序开始是单 线程的 耗时操作移到子线程 永远不要阻塞主线程 IntentReceiver 中要快 长时间操作用后台服务 来完成
来源于Android的设计 如@Override protected void onCreate(Bundle state) { super.onCreate(state); TextView label = new TextView(this); label.setText("Leaks are bad"); setContentView(label); }
Time 1 4 5 5 12 12.5 15 165 600 22,000 25,000 100,000 135,000 3,000,000
让它看上去很快
针对应用程序响应不够灵敏的技巧 只要让用户觉得就行
ANR – 应用没有反应
( ANR : Application Not Responding) 如果应用程序不能响应 用户输入的话 来让用户选择杀死应用 程序
传统原因
非常方便 让你的API更出色,并能提供编译时的检查
Android 中的问题
牺牲执行的速度和并大幅增加文件体积 增加新的class文件
解决之道
用ordinal()方法获取枚举变量的整数值
避免使用浮点数
传统原因
让你的游戏运行得更顺畅
Android 中的问题
适应Android的规定
很多用起来很别扭
没办法, Live with it
后台任务
使用Android 的Service体系结构
前台Activity的生命周期
退出前台时关闭不必要的资源 onDestroy() 时关闭一切资源使用 在OnCreate()时重新创建资源的使用
Android 的内存限制
跟踪文件必须是完整路径 (2.1版) 如果日志或跟踪文件过大,结果无法启动java虚 拟机 , 则需要手动修改traceview来扩大Java VM的 heap size, 增加 如 –Xmx512M 等选项来 扩大内存大小。
时间线面板
- 描述当每个线程和方法开始和停止
Profile 窗口
在极少数情况下
NDK可能会比较难学习 本机代码很难编程 本机代码很难调试 本机代码能很难移植 本机代码可能很难融入现有的代码和框 架
可能需要ARM汇编代码
只在一个很有限的范围内考虑使用本机 代码 或尽可能地使用Android提供的本机代 码
重新设计算法
好算法一个顶一万个 如冒泡和快速排序
代码和注意事项
代码
// start tracing to "/sdcard/calc.trace" Debug.startMethodTracing("calc"); // ... // stop tracing Debug.stopMethodTracing();
onStop()中调用Debug.stopMethodTracing() 跟踪时,代码将运行得比较慢 不要依赖分析器中的绝对计时 仿真器必须有一个SD卡
用户的体验始终是最优先的事项
对用户来数,使用的顺畅是第一优先
解决方法
将小对象的分配放在关键代码之后,或之前 或将许多小对象的分配合并为大对象的分配。
调试和优化工具
DDMS (Dalvik 调试监测)工具
多个工具的组合 内存分配跟踪器 VM 内存堆 内存信息图 CPU负载图
增强响应灵敏性
100-200ms 法则
用户能感知阻滞的时间阈值
告诉用户要等待
告诉用户要等待 ProgressBar和ProgressDialog
显示 Splash 屏幕
耗时的初始化过程
用源码吧, 伙计
强烈建议您阅读Android的源代码
看看你的代码在哪里和怎样被调用 学习系统的构成 发现新的API
性能优化的原则
原则
设计上的优化永远优于代码上的优化 不要做不必要的事 不要分配不必要的内存
用户体验
程序是否响应快速而灵活 不要寄希望于JIT编译器
体系结构上的优化
是最具影响力的 不取决于那个系统
使用本机代码
编译的C / C + +
一个字:快
Android NDK
JNI
CPU限制
不可能有无限快的CPU CPU越快,电池消耗越大 多个应用程序可能 会在同一时间争夺
内存和电源限制
记忆体在移动世界里是珍贵资源 8G或16G记忆体是指闪存记忆 没有无限大的电池或永远连着的电源
应用程序必须尽量节省电池使用
Android应用程序要快、要有效
模拟器 !=真正的移动设备 将内存分配保持在最低水平 紧凑的风格 尽量少用计算能力和数据存储 适合小屏幕 延长有限的电池寿命
记住Garbage Collector对此类内存泄漏无 效
Garbage Collector -垃圾收集器的影响
垃圾收集器被启动时会暂时停止应用程序
大多数情况下发生得够快的话没有人会注意到
但是在性能敏感的代码路径如游戏或绘制视图
用户会感觉 ‘卡’ 通常垃圾收集有可能会需要以100至200毫秒 顺畅的动画需要在16至33毫秒中画每个帧 Android的垃圾收集器,还没有能够进行优化
性能分析工具Traceview
将函数的调用情况以及调用时间保存到一个lo(Allocation Tracker)
VM 内存堆
性能分析工具Traceview
创建跟踪文件
生成包含您要跟踪信息的日志文件
在您的代码中加上 Debug类 调用startMethodTracing()方法 执行代码 呼叫stopMethodTracing()停止跟踪
提供了方法内发生事件的总结
Linux 工具
Android 是Linux 系统
如进程列表 /proc etc
通用代码级的性能和优化技巧
缓存成员变量到本地
访问成员变量比访问本地变量慢得多
缓存成员变量到本地
访问成员变量比访问本地变量慢得多
int count = this.mCount; Item[] items = this.mItems; for (int i = 0; i < count; i++) dumpItems(items[i]);
使用实类比接口好
Map myMap1 = new HashMap(); HashMap myMap2 = new HashMap();
传统的观点
可以改变他的具体实现类
Android问题
调用一个接口的引用会比调用实体类的引用多花 费一倍的时间
解决之道
能用具体实现类就直接用
不用getter和setters
Android应用程序只能用有限的内存
16M for(G1)
方法
避免建立对象
避免创建短命的临时对象 防止周期性的垃圾回收 减少对用户体验的影响
int数组比Integer数组好 把多维数组分成多个一维数组