Seguindo os tópicos levantados em outras questões, acredito que quando o Linux Kernel está tentando liberar RAM física, ele toma algum tipo de decisão entre descartar páginas de seu cache de disco ou liberar outras páginas para swap. Não tenho certeza disso, talvez eu tenha entendido mal o mecanismo.
Em qualquer caso, há sinergia entre:
- o kernel mantendo seu próprio cache de disco interno
- programas arquivos de mapeamento de memória
- memória de aplicativo "regular" sendo colocada em um arquivo de troca
Todos os três podem ser usados para liberar RAM física, todos os três dependem de gravar páginas "sujas" no disco ou simplesmente saber que as páginas já estão duplicadas no disco e descartá-las da alocação física de RAM.
Com o espaço de troca, partições e arquivos de troca individuais podem ter prioridade para que dispositivos mais rápidos sejam usados antes de dispositivos mais lentos. Não tenho conhecimento de tais configurações para outros dispositivos que não sejam de troca.
Minha pergunta é: Como o Kernel decide qual RAM liberar?
- É puramente baseado no último acesso?
- O Kernel usa todos os três acima igualmente?
- existe alguma priorização entre eles (e discos individuais)
- é configurável?
Esta pergunta é impulsionada por experiências semelhantes a esta, mas quero que essa pergunta se concentre no mecanismo subjacente NÃO na solução de um problema específico.
O nome dado à tarefa geral de liberar páginas físicas de memória é recuperação e abrange várias tarefas. A recuperação é principalmente impulsionada por alocações de página, com vários níveis de urgência. Em um sistema descarregado, as alocações de página podem ser satisfeitas sem esforço e não acionam nenhuma recuperação. Em sistemas carregados moderadamente, as alocações de página ainda podem ser satisfeitas imediatamente, mas também farão
kswapd
com que sejam despertadas para executar a recuperação de segundo plano. Em sistemas carregados em que as alocações de página não podem mais ser atendidas imediatamente, a recuperação é executada de forma síncrona.Páginas recuperáveis são páginas que armazenam conteúdo que pode ser encontrado ou disponibilizado em outro lugar. É aqui que entra em jogo o típico ato de equilíbrio: memória cujo conteúdo também está em arquivos (ou deveria terminar em arquivos), v. memória cujo conteúdo não está (e precisa ser trocado). As primeiras são armazenadas no cache de página, as últimas não, razão pela qual as explicações de balanceamento geralmente falam sobre cache de página vs. swap.
A decisão de favorecer um sobre o outro é determinada em um único local no kernel,
get_scan_count
, controlado pelas configurações emstruct scan_control
. A finalidade desta função é descrita a seguir:Talvez surpreendentemente para uma função chamada
get_...
, isso não usa um valor de retorno; em vez disso, ele preenche a matriz apontada pelounsigned long *nr
ponteiro, com quatro entradas correspondentes a páginas inativas anônimas (páginas sem suporte, não usadas recentemente), páginas ativas anônimas (páginas sem suporte, usadas recentemente), arquivo inativo páginas (páginas não usadas recentemente no cache de página) e páginas ativas de arquivo (páginas usadas recentemente no cache de página).get_scan_count
começa recuperando o valor de “swappiness” apropriado, demem_cgroup_swappiness
. Se o cgroup de memória atual for um cgroup v1 não-root habilitado, sua configuração de swappiness é usada; caso contrário, é o infame/proc/sys/vm/swappiness
. Ambas as configurações compartilham o mesmo propósito ; eles dizem ao kernelAntes de realmente usar esse valor,
get_scan_count
determina a estratégia geral que deve ser aplicada:Depois de determinar a estratégia, ele itera sobre todas as LRUs elimináveis (anônimas inativas, anônimas ativas, apoiadas por arquivos inativos, apoiadas por arquivos ativos, nessa ordem) para determinar quantas páginas de cada uma devem ser verificadas; Vou ignorar v1 cgroups:
scan_control
de deslocamento de ;priority
priority
), nenhuma nas outras LRUs;A varredura de página real é conduzida por
shrink_lruvec
, que usa os comprimentos de varredura determinados acima e reduz repetidamente as LRUs até que os destinos sejam alcançados (ajustando os destinos à medida que avança de várias maneiras). Feito isso, as LRUs ativas/inativas são reequilibradas.Voltando às suas perguntas:
swappiness
, cgroups, limites de marca d'água baixos...).A prioridade de troca só determina para onde uma página vai depois que for decidido trocá-la. (Aliás, a
swappiness
documentação e as explicações acima devem deixar claro que não há granularidade suficiente no custo de E/S para lidar bem com configurações mistas de troca de ZRAM/disco...)Há muito mais para explicar, incluindo como
scan_control
é configurado, mas suspeito que isso já seja muito longo! Se você deseja rastrear o custo de recuperação, pode vê-lo na contabilidade de atraso de tarefa (consulte tambémstruct taskstats
).