文章

内存优化基础

内存优化基础

内存优化基础

物理内存和虚拟内存

现代操作系统都不直接操作物理内存,而是虚拟内存。App 申请的内存也都是虚拟内存。
对于每个 app 来说,在 32 位操作系统,都认为自己的进程独享 2^32 容量的虚拟内存,实际上占用多少物理内存,用的时候再去分配,64 位系统是 2^48,而不是 2^64,因为 256TB 足够大了,用 2^64 会有大量寻址空间浪费。

虚拟内存分为用户空间和内核空间,对于 32 位系统,内核空间所有进程共享,大小 1GB,用户空间不共享,大小 3GB

Android 内存分配策略

  1. 静态分配,使用方法区,存储已被虚拟机加载的类信息、常量、静态变量等;在程序编译时就已分配好,存在于程序整个运行期间(不需要回收的)
  2. 栈式分配,使用栈区,方法执行时以栈帧的形式存储局部变量、数据类型和对象的引用等;方法结束后栈帧自动释放内存
  3. 堆式分配,使用堆区,存储 Java 对象实例;由 GC 自动管理内存回收

内存释放策略

其实就是垃圾回收算法。

  1. 标记清除,先标记后清除,会产生大量不连续的内存碎片,效率低,一般用于老年代
  2. 复制,内存一分为二,适用于新生代
  3. 标记 - 整理,老年代
  4. 分代收集,现在虚拟机基本都采用这种,新生代采用复制算法,老年代采用标记清除/标记 - 整理算法

keilv

内存数据的获取

内存指标

#

内存优化方法论

  1. Java 堆(Java Heap)内存优化
  2. Native 内存优化
  3. 虚拟内存优化

Java 堆优化

Java 内存优化的 3 条方法论:

  1. 减少加载进程 Java 堆的数据
  2. 及时清理加载进 Java 堆的数据
  3. 增加 Java 堆空间可用大小

减少加载进 Java 堆的数据

减少缓存大小

缓存是通过空间换时间的方式提升业务体验。
以 LruCache 为例,一般说缓存 size 设置为最大可用堆的 1/8,这样设置其实不太准确,需要评估业务的重要性和业务使用频率

  • 使用频率高的 size 多设置一点
  • 评估机型,堆空间的大的 512M,size 设置为 1/8;低端机设置为 1/9 等
  • 及时清理缓存,超过 Java 内存 80% 就清理 LruCahe 的数据

按需加载数据

真正用到的时候再去加载数据

转移数据

Java 堆大小有限制,主流只有 512M,转移数据的方式有 2 种:

  1. 将 Java 堆的数据转移到 native
  2. 将当前进程中 Java 堆的数据转移到其他进程中:如 WebView,小程序等。

及时清理加载进 Java 堆的数据

增加 Java 堆的大小

Native 内存优化

https://swe84nm8d7.feishu.cn/wiki/wikcnXi38oIwe03FmPULuNs24ef

虚拟内存优化

1. 线程池 - 线程收敛

每个线程,空的都要占用 1M 的虚拟内存空间

2. hook 将 1M 的空间改为 512K

繁重的线程不修改

其他

Bitmap 相关

  1. 使用 Bitmap 解码格式 AGRB_888、ARGB_565、ARGB_4444、ALPHA_8
    代码质量
  2. 用 shape 替代图片
  3. RecyclerView item 复用
  4. 使用对象池
  5. 使用线程池
  6. 谨慎使用帧动画
  7. onTrimMemory() 释放资源

大图优化?

通过 Flipper 等工具查看应用中的大图

代码优化

HashMap 替代品

  1. ArrayMap 替换 HashMap;底层是 array,少创建 HashMapEntity,还是存在自动装拆箱问题
  2. SparseArray 替换 HashMap;底层是 int array,可避免装箱问题
  3. 1000 以内,key 为 int 的用 SparseArray,key 不是 int 的用 ArrayMap

Ref

「抄底 Android 内存优化 8」 —— 快手线上 OOM 监控学习笔记
内存优化 · 方案篇 · 安卓native内存分析

内存优化相关问题?

线上做内存泄漏检测有什么思路吗?

线上内存怎么监控?

什么时候 dump 内存?如何 dump 内存?dump 下来怎么裁剪、上传、分析?

KOOM、LeakCanary 和 Matrix 方案?

  • LeakCanary 和 Matrix 由于 dump 的整个过程会影响到主进程,所以基本应用与线下监控
  • KOOM 提出了 fork dump 的概念,能在 dump 分析内存泄漏的时候而不影响主进程的应用运行,适合线上监控

有什么实际解决 UI 卡顿优化的经历

有做过什么 Bitmap 优化的实际经验

mainfest 中配置 LargeHeap,真的能分配到大内存吗?

当 largeHeap=true 时:结论就是,设置 largeHeap 的确可以增加内存的申请量。但不是系统有多少内存就可以申请多少,而是由 dalvik.vm.heapsize 限制

本文由作者按照 CC BY 4.0 进行授权