Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Firefox OS 中的内存溢出管理

Firefox OS 运行在一些严重内存受限的设备上时,就会很容易出现app在运行时将内存耗尽的情况。当一个进程将系统上可用的内存耗尽时, 为了能够释放内存,kernel 层必须要 kill 掉其他的进程。本文则描述了低内存 killer和 低内存通知器是如何工作的 。

FxOS 的操作会涉及到多进程问题—一个“主进程”运行基本的系统服务和潜在众多的“子进程”。FxOS 环境下应用很少会由用户主动关闭,因此当新的 app需要空间或已存在的 app需要额外的内存时, system会自动对应用程序的生命周期进行管理。

有两个子系统负责这方面的管理:  低内存管理器 Low memory killer (LMK) 和低内存通知器Low memory notifications.

低内存管理器 Low memory killer

 LMK 是 Android 内核的子系统,当有获取内存空间的需求时,能够自动的对进程进行查杀。为了能够选择出哪一个进程需要第一个查杀,每个进程都要通过 /proc/<pid>/oom_adj or /proc/<pid>/oom_score_adj files 来设定一个优先级。 每个进程的优先级也可称为调整分数或 oom_adj.  oom_adj ,值越小则表示器进程优先级越高。

一般来说,进程的调整得分越高,越可能被查杀。 LMK 提供了多个等级,每一个都与一定程度的闲置内存和最小调整分数对应。当闲置内存的数量低于某个特定等级时,所有高于该等级指定的最小调整分数的进程都具有被查杀的可能。LMK会开始查杀这些进程,分数高的会被先杀掉,直到闲置内存再次高于临界值为止。

Note: When a background app is killed by the LMK, it is made available in the task manager/through edge swipes as a "zombie app": next time you browse to that app, it will be revived. The maximum number of apps that can be kept in this state is currently 10.

注意: 当设备存储器不足(oom) 时杀掉的进程并不一定是导致存储器不足(oom)的原因。

进程优先级

Firefox OS 中的 app 是以下面的优先级次序策略来管理的,这种策略是根据每个应用的优先级等级和这些等级相关的 OOM 调整分数 (the current values are set in prefs)而制定的: 

  1. 后台应用会首先被干掉,先从使用最少的应用开始
  2. 之后会干掉 homescreen 应用程序
  3. 可由用户感知的后台应用会被干掉 (例如, 在后台播放音频的音乐播放器或者持有  high-priority 或 cpu wakelock,并且注册系统消息的处理程序)
  4. 如果 keyboard 应用正在运行,会被干掉
  5. 前台应用被干掉
  6. 最后,已请求  high-priority 或 cpu wakelocks 的前台应用会最后被干掉

注意: 当子进程在前台时,会以  oom_adj 2 运行。后台的子进程运行时,其 oom_adj 会在 3 和 6 (包括6) 之间。后台运行的子进程  oom_adj 数值要取决于许多因素,如是否播放音乐,是否是homescreen 等。

也有两个例外的情况:

  • 主进程是不会被 LMK 干掉的,否则就会干掉所有的子进程并且重启操作系统。主进程运行时 oom_adj 0.
  • 我们会保持一个名为 preallocated process 的进程以加速新应用的启动这个进程通常需要一直存在,因为它消耗很有限的内存,而且能够明显提高应用程序的启动速度。它只在一种情况下被干掉,就是主线程需要内存保持运行,杀掉其他进程后, 内存空间还不够时。

低内存通知器 Low memory notifications

释放内存的第二种机制就是低内存通知器。 LMK 提供一个特定的门限值,当超出该值时,会通知用户当前系统已运行在低内存状态。system 应用和常规的用户应用都会持续的等待这个条件,并通过 observer service 发送一个 memory-pressure 方法来响应它。 这个事件只对 C++ 和 chrome JS 代码可见,并非由应用直接发送。通过Gecko 代码库,我们使用该事件可以释放尽可能多的内存— 一般会通过清除内部缓存(图片,DNS,数据库等),丢弃可重新创建的资源(例如, WebGL contexts)以及运行垃圾回收器,生命周期回收器等方式实现。

当低内存情况发生时, 触发的第一个 memory-pressure 事件会有一个 low-memory 负载。 如果在预订时间(5s) 后, 还处在低内存状态, 会触发另一个 memory-pressure 事件,但此次负载值变为 low-memory-onging 。当一直处在低内存条件下,并且要清除缓存以及做其他简单的内存削减时,该负载会被使用,但应当知道一些繁重的工作,如 GC , 是不能成功的。(此段翻译可能不是太贴切,要深入理解,还请参考英文原文)

 LMK 和低内存通知器是如何配合工作的

当前低内存限值设定在后台进程 LMK 等级和 homescreen 之间。 因此当设备在低内存状态下运行时, LMK 和 低内存通知器联合作出的反应如下:

  1. 以最不经常使用的次序 kill 掉 后台 app
  2. 如果我们没有释放足够的内存, 向所有现存的应用发送 memory-pressure 事件
  3. 如果低内存情况还在,每个 5 秒重发一次 memory-pressure 事件,但将它们标记为 ongoing , 使 GC/CC 不会对它们动作。
  4. Kill 掉 homescreen.
  5. Kill 掉可感知的或高优先级的后台应用
  6. 如果 keyboard app 正在运行,Kill 掉
  7. Kill 掉前台应用
  8. Kill 掉高优先级的前台应用
  9. Kill 掉 preallocated process

文档标签和贡献者

 此页面的贡献者: chrisdavidmills, ReyCG_sub
 最后编辑者: chrisdavidmills,