Gerenciamento de falta de memória no Firefox OS

Este artigo necessita de uma revisão editorial.

O Firefox OS roda em alguns dispositivos com baixa capacidade de memória, e é fácil que estes aplicativos esgotem a memória em tais sistemas. Quando um processo esgota a memória disponível do sistema, o kernel deve encerrar alguns processos para liberar memória. Este artigo descreve como o "low memory killer" e "low memory notifications" funcionam — os dois sistemas no dispositivo controlam quais processos devem ser encerrados para manter o sistema principal funcionando sem que ele fique sem memória.

FxOS funciona com vários processos envolvidos — um "processo principal" que executa os serviços básicos do sistema e potencialmente muitos "processos filhos". Em geral todo aplicativo é executado em seu próprio processo filho. Uma vez que as aplicações do ambiente FxOS são raramente fechadas pelo usuário, o sistema automaticamente gerencia o tempo de vida para liberar mais espaço para novas aplicações ou para aplicações que estejam sendo executadas e que necessitem mais espaço de memória.

Dois subsistemas são usados para gerenciar isto: o Low memory killer (LMK  Finalizador de memória baixa)Low memory notifications (Notificações de pouca memória).

Low memory killer

O LMK é um subsistema do kernel do Android que encerra automaticamente os processos  para dar lugar a pedidos de memória. Para escolher qual o processo deve ser encerrado primeiro para liberar memória, a cada processo é atribuido uma prioridade através dos arquivos /proc/<pid>/oom_adj ou /proc/<pid>/oom_score_adj. Um processos tem uma prioridade conhecida como prontuação de ajuste, ou oom_adj.  Valores menores de oom_adj corresponde a processos de maior prioridade.

Em geral, quanto maior for a pontuação de ajuste, maior a probabilidade de ser o escolhido para ser encerrado. O LMK oferece múltiplos níveis, cada um correspondendo a uma certa quantidade de memória livre e uma mínima de pontuação de ajuste. Sempre que a quantidade de memória livre no sistema cair abaixo de um certo nível, todos os processos com uma pontuação de ajuste maior do que o mínimo especificado para este nível são elegíveis para ser encerrado. O LMK irá começar a encerrar esses processos, os maiores em primeiro lugar, e continuará até que tenha liberado memória suficiente de acordo com o limite definido.

Nota: O processo encerrado quando o dispositivo ficar sem memória não é necessariamenteo que "causou" a condição de falta de memória.

Prioridades de processos

No Firefox OS os aplicativos são encerrados seguindo a política de ordem de prioridade, que é imposta dando a cada aplicação um nível de prioridade e associando uma pontuação de ajuste (OOM) a esses níveis. (os valores correntes são definidos em prefs):

  1. Os primeiros aplicativos a serem encerrados serão os aplicativos em segundo plano, iniciando pelos menos utilizados recentemente.
  2. O aplicativo homescreen é o próximo a ser encerrado.
  3. Em seguida, são encerrados os aplicativos em segundo plano que são perceptíveis pelo usuário (por exemplo, um leitor de música reproduzindo áudio em segundo plano ou um aplicativo que possua um wakelock de high-priority ou cpu  e ter um manipulador de mensagens de sistema registrado.)
  4. Se o teclado estiver em uso, será o próximo a ser encerrado.
  5. Aplicações em primeiro plano serão as próximas a serem encerradas.
  6. Finalmente, aplicações em primeiro plano que solicitaram um wakelock  high-priority ou cpu serão as últimas a serem encerradas.

Nota: Muitos "processos filhos" são executados com oom_adj 2 enquanto estão em primeiro plano. Ao serem executados em segundo plano o valor de oom_adj ficam entre 3 e 6 (inclusive).  O valor exato de oom_adj de um processo filho depende de vários de fatores: se está tocando uma música, se é o aplicativo de tela inicial, etc.

Existe algumas excessões para essas regras:

  • O processo principal nunca é terminado pelo LMK, pois se isso for feito todos os demais processos serão terminados e o sistema operacional seria reiniciado. O processo principal é executado com oom_adj 0.
  • Nós mantemos um processo que é utilizado para acelear o início de novos aplicativos chamado preallocated process. Normalmente esse processo é mantido ativo pois consome pouca memória e permite uma maior velocidade ao iniciar um aplicativo. A única situação na qual esse processo pode ser terminado é se não existir memória suficiente para o processo principal manter-se ativo após os outros processos terem sido terminados.

Low memory notifications

O segundo mecanismo utilizado para liberar memória é a Notificação de pouca memória ou Low memory notifications. O LMK fornece um limite especial que quando ultrapassado pode enviar notificações para o userspace informando que o sistema está sendo executado com pouca memória. Tanto os aplicativos de sistema quanto os aplicativos regulares estão projetados para reagir ao evento memory-pressure via o serviço observer. Esse evento é visível apenas por códigos C++ e chrome JS e não diretamente pela aplicação. Através do codebase do Gecko nós usamos esse evento para liberar a maior quantidade de memória possível — normalmente purgando caches internos (imagens, DNS, sqlite, etc), descartando objetos que podem ser recriados (contextos WebGL por example) e executando o garbage collector e cycle collector.

Quando for encontrada uma condição de pouca memória o primeiro evento memory-pressure enviado possuirá o parâmetro low-memory. Se após um período pré-definido (5s) persistir a condição de pouca memória, um outro evento memory-pressure será disparado, mas dessa vez com o parâmetro low-memory-ongoing. Esse parâmetro é utilizado quando continuamos com a condição de pouca memória e gostaríamos de liberar caches e utlizar outras formas "mais baratas" de minimizar o uso da memória, mas sabendo que abordagens mais pesadas como GC (Garbage Collector) provavelmente não terão sucesso.

Como LMK e as notificações de pouca memória trabalham juntos

Atualmente o limite de pouca memória é definido abaixo do nível do LMK para aplicativos em segundo plano mas abaixo de um para a tela inicial. Assim, as ações  agregadas para o LMK e notificação de pouca memória quando um dispositivo possui pouca memória:

  1. Terminar aplicativos em segundo plano em ordem dos menos usados recentemente.
  2. Se não for liberada memória suficiente envia o evento memory-pressure para os aplicativos remanescentes.
  3. Se a condição persistir é renviado um evento memory-pressure a cada 5 segundos, mas marcando-os como em execução para que os processos de GC/CC (Garbage Collector e Cycle Collector) não respondam a eles.
  4. Terminar o aplicativo Tela Inicial.
  5. Terminar aplicações em segundo plano perceptíveis e de alta prioridade.
  6. Terminar o aplicativo teclado se estiver sendo executado.
  7. Terminar aplicativos em primeiro plano.
  8. Terminar aplicativos em primeiro plano de alta prioridade.
  9. Terminar os processos pré-alocados.

Etiquetas do documento e colaboradores

Última atualização por: rbrandao,
Esconder painel