内存优化

2019-08-22  本文已影响0人  修塔寻千里

一、内存问题

1、很多的异常退出、崩溃和卡顿都是由内存引起的,所以内存相关的优化是开发人员经常要面临和处理的难题。内存主要造成两个问题:

image.png

2、内存使用方面有两个误区

  1. 在Android 3.0之前,Bitmap对象放在Java堆,而像素数据放在Native内存中,如果不手动调用recycle,Bitmap Native内存回收完全依赖finalize函数回调,而finalize函数回调的时机十分的不靠谱。
  2. Android 3.0~ Android 7.0将Bitmap对象和像素数据统一放到Java堆中,这样就算我们不调用recycle,Bitmap内存也会随着对象一起回收。然而Bitmap是内存消耗大户,常常会导致Java堆内存不足而OOM。
  3. Android 8.0之后,利用NativeAllocationRegistry机制做到像素数据放在Native内存中,Bitmap对象放在Java堆中,和对象一起快速释放。

Fresco图片库在处理图片时就是将图片存储在Native内存中,在Android 5.0~7.0采用的方法如下:
步骤一:通过直接调用libandroid_runtime.so中Bitmap的构造函数得到一张空的Bitmap图片对象,而它的内存是放到Native堆中;
步骤二:通过系统的方式创建一张普通的Java Bitmap;
步骤三:将Java Bitmap的内容绘制到之前申请的空的Native Bitmap中;
步骤四:将申请的Java Bitmap释放,实现图片内存的”偷龙转凤“。

二、测量方法

1、Java内存分配

跟踪Java堆内存的使用情况,常用的工具是Allocation Tracker和MAT。
Allocation Tracker有三个缺点:

2、Native内存分配

谷歌建议我们使用Chromium的AddressSanitize,目前其内存泄漏检测支持x86_64 Linux和OS X系统。另外还可以使用Malloc调试和Malloc钩子的方式监测内存问题。Malloc调试可以帮助我们去调试Native内存的一些使用问题,例如堆破坏、内存泄漏、非法地址等。Malloc钩子是在Android P之后,Android的libc支持拦截在恒旭执行期间繁盛的所有分配/释放调用,这样我们可以构建自己的内存检测工具。

三、内存优化方案

1、设备分级

内存优化首先需要根据设备环境来综合考虑。

2、Bitmap优化

3、内存泄漏

内存泄漏主要分两种,一种是同一对象泄漏,另一种更加可怕,每次都会泄漏新的对象。

4、内存监控

1.采集方式
在前台时,可以间隔时间采集一次PSS、Java 堆、图片总内存。也可对用户进行抽样采集,全天采集。
2、计算指标
内存异常率:可以反映内存占用的异常情况,
内存 UV 异常率 = PSS 超过 400MB 的 UV / 采集 UV
触定律:可以反映Java内存的使用情况,如果超过85%最大堆限制,GC会变得频繁,容易造成OOM
内存 UV 触顶率 = Java 堆占用超过最大堆限制的 85% 的 UV / 采集 UV
3、GC监控
Android 6.0之后系统可以拿到更加精准的GC信息,需要特别注意阻塞式GC凡人次数和耗时,因为它会暂停应用线程,可能导致卡顿和ANR。

上一篇 下一篇

猜你喜欢

热点阅读