内存优化

内存优化

意义:减少因为频繁GC导致的卡顿,减少因为内存占用应用存活率降低

内存问题

  • 内存抖动:表现为内存锯齿状,频繁GC,导致卡顿
  • 内存泄露:可用内存减少,频繁GC
  • 内存溢出:OOM、程序异常

相关工具的使用

参考:Memory Profiler

参考:Memory Analyzer

参考:Leak Canary

DalvikArt 的区别

  • Dalvik 仅固定一种回收算法
  • Art 回收算法可运行期切换,具备内存整理能力,减少内存空洞

Low Memory Killer

  • 进程分类(优先级从高到低):前台进程、可见进程、服务进程、后台进程、空进程
  • 回收收益:系统会考虑回收收益执行回收力度

内存抖动

内存频繁分配和回收导致内存不稳定,频繁 GC ,易导致卡顿和 OOM

频繁创建对象、释放对象,导致内存碎片化严重

不连续的内存片无法被分配,导致 OOM

解决技巧:通过 Memory Profiler 找对象,重点寻找循环或者频繁调用的地方

【注意】内存泄漏造成内存减少,也会出现频繁回收对象而出现内存抖动

内存泄漏

dump 出的内存文件通过 Memory Analyzer 工具进行分析

参考:Memory Analyzer

参考:dump 内存的几种方式

大图监控

由于图片是占用内存的大头,所以必须对其严格控制,可以使用 AOPART 方式获取相应控件的大小和 Bitmap 的大小,提前警告

参考:ART-Hook

参考:Aspectjx

线上内存监控

  • 常规方案:超过最大内存80%,Dump 内存,待到 wifi 环境下回传文件分析
    • Dump 文件太大,和对象数正相关,可剪裁
    • 文件较大上传失败率高,分析困难
    • 效果有限
  • LeakCanary 线上监控,预设怀疑点,发现泄漏回传
    • 不适合所有场景,需要预设坏一点
    • 该库分析比较耗时,容易OOM
    • 建议定制 LeakCanary

线上监控完整方案

  • 待机内存、重点模块内存、OOM率
  • 整体及重点模块GC次数、GC时间
  • 增强 LeakCanary 自动化内存泄漏分析

优化大方向

  • 内存泄漏
  • 内存抖动
  • Bitmap

优化细节

  • 设置 LargeHeap 属性,向系统申请更多内存

  • 系统回调 onTrimMemory 根据回调级别做适当的资源释放,当系统回调严重级别时可以将所有界面关闭强制重启主界面的操作

  • 使用优化过的集合:SparseArrayArrayMap,性能虽不及 HashMap,但在数据量较少的情况下是可以接受的

  • 谨慎使用 SharedPreference,首次加载时会将涉及的文件所有数据加载到内存里,如果单个文件过大造成内存占用过多

  • 可以考虑使用 IntDef StringDef 来减少枚举类型的使用

  • 谨慎使用外部库

  • 尽可能使用静态内部类减少外部引用

  • 图片优化

    • 对图片质量要求不高的可以适当降低图片质量,如 ARGB_4444 或 RGB_565
    • 适当对图片进行缩小加载
    • 重用 Bitmap 内存
    • 类似 Glide 图片加载库,默认兼容 gif 和 webp,但是执行效率和内存使用率并不高,可以接入 giflib 和 libwebp 进行优化
    • Item 被回收不可见时释放图片的引用
      • ListView:条目被回收后都会重新绑定数据,只需要在 ImageView.onDetachFromWindow() 时释放图片引用
      • RecycleView:当条目不可见时优先放入 mCacheView 缓存中,重新展示并不会触发 bindViewHolder 来绑定数据,只有被收录到 mRecyclePool 中才会拿出来复用并绑定,需要在 Adapter.onViewRecycled() 函数中释放图片引用,该函数会在条目收录到 mRecyclePool 缓存时回调