Android性能优化总结

时间:2021-12-08 06:03:54
面试的时候,基本都会问到性能优化的知识点。从用户角度来说,能够感知的性能问题,基本上是慢卡顿问题,如果不考虑系统问题,单从应用角度来说,能够优化用户感知的性能问题的,可以从资源和体验角度着手。资源角度,包括硬件资源,CPU、GPU、内存、硬盘;软件资源,代码和算法。体验角度,动画和数据加载优先级。下面就从这几个方面着手分析,可能还存在其他优化方式,就不一一描述啦。 一、涉及CPU方面的优化 1.线程优化 cpu的最小调度单位是线程,java虚拟机中的线程很大程度上是基于操作系统的线程模型的,不是线程个数越多,运行越快,相反的,当线程过多时,由于涉及到线程切换,效率会降低,一般来说线程个数设置为CPU个数+1,能够实现最优的效率(《java并发编程》)。 下面是摘抄自知乎上的答案:https://www.zhihu.com/question/38128980 一般说来,大家认为线程池的大小经验值应该这样设置:(其中N为CPU的个数) a.如果是CPU密集型应用,则线程池大小设置为N+1 b.如果是IO密集型应用,则线程池大小设置为2N+1 如果一台服务器上只部署这一个应用并且只有这一个线程池,那么这种估算或许合理,具体还需自行测试验证。 但是,IO优化中,这样的估算公式可能更适合: 最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目 因为很显然,线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。 下面举个例子: 比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,那么根据上面这个公式估算得到:((0.5+1.5)/0.5)*8=32。这个公式进一步转化为: 最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目 2.CPU内核个数优化 如果有可能,可以设置需要运行的CPU个数
二、涉及GPU方面的优化 1.硬件加速 GPU的绘制包含软绘制和硬绘制,可以在代码或者AndroidManifest.xml文件中开启硬件加速,有时候硬件加速会引起一些问题,需要合理调用。 2.绘制流程优化 绘制流程的三大关键步骤,会分别调用onMessure、onLayout、OnDraw,三个过程会从根节点开始遍历子节点,因此从绘制流程来看,优化的方法有: a.布局优化,减少布局层次 b.使用合理的布局,其中效率方面FrameLayout>LinearLayout>RelativeLayout(相同层次的情况下) c.这三大方法里面不要做耗时操作 d.布局中合理使用include、merge、ViewStub方式加载布局 e.特别的ListView的优化,复用convertView ,使用VIewHolder减少findViewById操作,使用tag保存ViewHolder等等 f.实现局部绘制,调用canvas.clipRect方法或者canvas.drawBitmap(bitmap, src, des, paint)方法 g.由于前一个Activity调用完onPause之后才会启动后一个Activity,因此onPause和onCreate、onStart里面都不要做耗时操作 h.四大组件启动的时候,都会实例化Application,因此在Application的onCreate中也不要做耗时操作 i.自定义控件
三、涉及内存方面的优化 1.图片加载可以采用三级缓存 2.使用图片时,可以的话,对图片进行缩放,采样率,图片格式(png、jpg、.9图),合理使用ARGB_4444、ARGB_8888、RGB_565、ALPHA_8 3.如果采用强引用使用大内存对象(比如图片),使用完及时回收 4.合理使用强引用、软引用、弱引用 5.避免频繁申请和释放对象,内存不足的情况下,容易引起gc 6.复用对象,android有很多复用对象的范例,比如Message.obtain或者Integer(-128~127),Parcel.ontain等 7.使用共享内存(Picasso使用了共享内存,避免gc)或者native代码中分配内存(这块内存不归java虚拟机管) 8.对内存占有量进行监控,及时回收内存(OnLowMemory/OnTrimMemory) 9.避免内存泄露,从java虚拟机的方法区常量引用的对象、方法区静态属性引用的对象、虚拟机栈引用的对象、本地方法栈引用的对象作为gc root出发的强引用链上的对象都不会被回收,下面的几种情况会造成内存泄露。 a.静态变量引用某个对象(方法区静态属性引用的对象) b.static final修饰的变量引用的对象(方法区常量引用的对象) c.非静态内部类作为外部类的静态变量引用的对象(方法区静态属性引用的对象) d.单例的成员变量引用的对象,因为单例不会被释放(方法区静态属性引用的对象) e.使用了强引用的Handler的message做耗时操作(虚拟机栈引用的对象,从looper出发的一条强引用链) f.线程执行的过程中引用的外部对象(虚拟机栈引用的对象) g.注册的广播未反注册、cursor未关闭、io流未关闭等(本地方法栈引用的对象)
四、涉及硬盘方面的优化 1.数据存储的时候可以采用B+树(sqlite数据库文件组织方式)或者红黑树 2.对数据压缩保存 3.可以使用数据库保存数据,而不是文件(和第1条一样,数据组织方式) 4.数据库优化可以有表优化,视图优化,触发器优化,索引优化,查询语句优化(比如表链接)等
五、涉及代码和算法方面的优化 这一部分主要涉及的是代码方面的,通常情况下优化效果比较大 1.代码优化 代码逻辑优化,比如涉及到的不需要的数据库查询,网络查询等,比较耗时的逻辑可以去掉,很大情况是使用了第三方的库,里面的逻辑可以自己来修改,只保留必须的逻辑。 2.算法优化 这一块的优化效果应该是最明显的,比如时间复杂度为O(n^2)优化成O(n)或者O(lgn)等
六、涉及体验方面的优化 1.动画优化 对动画执行时间可以进行优化,比如ios缩短了动画时间之后,看起来系统更流畅了 2.数据加载优化 从用户角度出发,优先显示必须的数据,把不必须的数据后面再加载,比如很多应用进入主界面同时开启了多个线程进行网络请求或数据库查询,可以对请求进行优先级处理,优先请求必须的数据,延迟请求不重要的数据;按需加载数据,比如listview加载图片的时候,只有当用户滑动屏幕结束同时手指离开屏幕的时候,才加载显示给用户的图片,其他不可见的图片不加载等等。
七、常用的优化工具 1.Traceview Traceview是Android平台特有的数据采集和分析工具,它主要用于分析Android中应用程序的hotspot。 使用方式参考:http://blog.csdn.net/innost/article/details/9008691/
2.Systrace Systrace是Android4.1中新增的性能数据采样和分析工具。它可帮助开发者收集Android关键子系统(如surfaceflinger、WindowManagerService等Framework部分关键模块、服务)的运行信息,从而帮助开发者更直观的分析系统瓶颈,改进性能。Systrace的功能包括跟踪系统的I/O操作、内核工作队列、CPU负载以及Android各个子系统的运行状况等。 使用方式参考:http://blog.csdn.net/innost/article/details/9008691/
3.Android Memory Monitor  Android Memory Monitor查看内存、cpu等运行状态的,可以进行内存泄露分析 使用参考:http://blog.csdn.net/chengliang0315/article/details/53780758
4.Mat 内存分析工具 使用参考:http://www.tuicool.com/articles/yaUZ3m
5.其他还有Hierarchy Viewer或者开发模式过渡绘制等等,下面给出一个性能分析工具的思维导图 Android性能优化总结