背景
根据Apple官方WWDC的回答,减少内存可以让用户体验到更快的启动速度,不会因为内存过大而导致Crash,可以让APP存活的更久。
对于高德地图来说,根据线上数据的分析,内存过高会导致导航过程中系统强杀OOM。尤其区别于其他APP的地方是,一般APP只需要关注前台内存过高的系统强杀FOOM,高德地图有不少用户使用后台导航,所以也需要关注后台的内存过高导致的系统强杀BOOM,且后台强杀较前台强杀更为严重。为了提升用户体验,内存治理迫在眉睫。
原理剖析
OOM
OOM是Out of Memory的缩写。在iOS APP中如果内存超了,系统会把APP直接杀死,一种另类的Crash,且无法捕获。发现OOM时,我们可以从设备->隐私->分析与改进->分析数据中找到以JetsamEvent开头的日志,日志里面记录了很多信息:手机设备信息、系统版本、内存大小、CPU时间等。
Jetsam
Jetsam是iOS系统的一种资源管理机制。不同于MacOS、Linux、Windows等,iOS中没有内存交换空间,所以在设备整体内存紧张时,系统会将一些优先级不高或者占用内存过大的直接Kill掉。
通过iOS开源的XNU内核源码可以分析到:
- 每个进程在内核中都存在一个优先级列表,JetSam在受到内存压力时会从优先级列表最低的进程开始尝试杀死,直到内存水位恢复到正常水位。
- Jetsam是通过get_task_phys_footprint获取到phys_footprint的值,来决定要不要杀掉应用。
Jetsam机制清理策略可以总结为以下几点:
- 单个APP物理内存占用超过上限会被清理,不同的设备内存水位线不一样。
- 整个设备物理内存占用受到压力时,优先清理后台应用,再清理前台应用。
- 优先清理内存占用高的应用,再内存占用低的应用。
- 相比系统应用,会优先清理用户应用。
Android端为Low Memory Killer:
- 根据APP的优先级和使用总内存的多少,系统会在设备内存吃紧情况下强杀应用。
- 内存吃紧的判断取决于系统RSS(实际使用物理内存,包含共享库占用的全部内存)的大小。
- 关键参数有3个:
1)oom_adj:在Framework层使用,代表进程的优先级,数值越高,优先级越低,越容易被杀死。
2)oom_adj threshold:在Framework层使用,代表oom_adj的内存阈值。Android Kernel会定时检测当前剩余内存是否低于这个阀值,若低于则杀死oom_adj ≥该阈值对应的oom_adj中,数值最大的进程,直到剩余内存恢复至高于该阀值的状态。