A memória “em cache” é de fato livre?

11

Ao executar cat /proc/meminfo, você obtém esses 3 valores no topo:

MemTotal:        6291456 kB
MemFree:         4038976 kB
Cached:          1477948 kB

Até onde eu sei, o valor "Em cache" são caches de disco feitos pelo sistema Linux que serão liberados imediatamente se qualquer aplicativo precisar de mais RAM; portanto, o Linux nunca ficará sem memória até que o MemFree e o Cache estejam em zero.

Infelizmente, "MemAvailable" não é relatado por / proc / meminfo, provavelmente porque está sendo executado em um servidor virtual. (A versão do kernel é 4.4)

Assim, para todos os fins práticos, a RAM disponível para aplicativos é MemFree + Cached.

Essa visão está correta?

Roland Seuhs
fonte
1
Eu não quero martelar ouro isto fechado, mas esta pergunta é relevante se não uma duplicata. Estou surpreso que você não tenha MemAvailable, foi adicionado em 3.14.
Stephen Kitt
A resposta aceites a partir dessa questão utiliza / proc / zoneinfo, que não está disponível no meu vserver bem
Roland Seuhs
uname -a: host Linux 4.4.0-042stab134.8 # 1 SMP sexta-feira, 7 de dezembro 17:16:09 MSK 2018 x86_64 x86_64 x86_64 GNU / Linux
Roland Seuhs
Eu suspeito que este seja um sistema OpenVZ com um kernel realmente baseado em 2.6.32, não 4.4.
Stephen Kitt
1
@sourcejedi e foi compilado exatamente ao mesmo tempo que o kernel 4.4!
Stephen Kitt

Respostas:

10

Essa visão pode ser muito enganadora em vários casos do mundo real.

O kernel agora fornece uma estimativa para a memória disponível, no MemAvailablecampo. Este valor é significativamente diferente de MemFree + Cached.

/ proc / meminfo: fornece memória disponível estimada [descrição da mudança do kernel, 2014]

Muitos programas de balanceamento de carga e colocação de carga de trabalho verificam / proc / meminfo para estimar a quantidade de memória livre disponível. Eles geralmente fazem isso adicionando "free" e "em cache", o que foi bom há dez anos, mas é praticamente garantido que ele esteja errado hoje.

Isso está errado porque o cache inclui memória que não pode ser acessada como cache de página, por exemplo, segmentos de memória compartilhada, tmpfs e ramfs, e não inclui memória slab recuperável, que pode ocupar uma grande fração da memória do sistema em sistemas inativos com muitos arquivos.

Atualmente, a quantidade de memória disponível para uma nova carga de trabalho, sem colocar o sistema em troca, pode ser estimada entre MemFree, Active (arquivo), Inativo (arquivo) e SReclaimable, bem como as marcas d'água "baixas" de / proc / zoneinfo. No entanto, isso pode mudar no futuro, e não se deve esperar que o espaço do usuário conheça os componentes internos do kernel para apresentar uma estimativa da quantidade de memória livre. É mais conveniente fornecer essa estimativa em / proc / meminfo. Se as coisas mudarem no futuro, só precisamos mudar isso em um só lugar.
...

Documentation / filesystems / proc.txt:
...
MemAvailable: Uma estimativa de quanta memória está disponível para iniciar novos aplicativos, sem troca. Calculado a partir do MemFree, SReclaimable, o tamanho do arquivo LRU e as marcas d'água baixas em cada zona. A estimativa leva em consideração que o sistema precisa de algum cache de página para funcionar bem e que nem todas as lajes recuperáveis ​​serão recuperáveis, devido ao uso de itens. O impacto desses fatores variará de sistema para sistema.

1. MemDisponível detalhes

Como diz acima, tmpfs e outras Shmemmemórias não podem ser liberadas, apenas movidas para troca. Cachedno /proc/meminfopode ser muito enganador, devido à inclusão desta swappable Shmemmemória. Se você tiver muitos arquivos em um tmpfs, ele poderá ocupar muito da sua memória :-). Shmemtambém pode incluir algumas alocações de memória gráfica , que podem ser muito grandes.

MemAvailabledeliberadamente não inclui memória trocável. Trocar demais pode causar longos atrasos. Você pode até optar por executar sem espaço de troca ou permitir apenas uma quantidade relativamente limitada.

Eu tive que verificar duas vezes como MemAvailablefunciona. À primeira vista, o código não parecia mencionar essa distinção.

/*
 * Not all the page cache can be freed, otherwise the system will
 * start swapping. Assume at least half of the page cache, or the
 * low watermark worth of cache, needs to stay.
 */
pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
pagecache -= min(pagecache / 2, wmark_low);
available += pagecache;

No entanto, eu achei corretamente tratados Shmemcomo memória "usada". Criei vários arquivos de 1 GB em um tmpfs. Cada aumento de 1 GB é Shmemreduzido MemAvailableem 1 GB. Portanto, o tamanho das "listas de arquivos LRU" não inclui memória compartilhada ou qualquer outra memória trocável. (Notei que essas mesmas contagens de página também são usadas no código que calcula o "limite sujo" ).

Esse MemAvailablecálculo também pressupõe que você deseja manter pelo menos o cache de arquivos suficiente para igualar a "marca d'água baixa" do kernel. Ou metade do cache atual - o que for menor. (Ele também assume as lajes recuperáveis). A "marca d'água baixa" do kernel pode ser ajustada, mas geralmente representa cerca de 2% da RAM do sistema . Portanto, se você quiser apenas uma estimativa aproximada, poderá ignorar esta parte :-).

Quando você está executando firefoxcom cerca de 100 MB de código de programa mapeado no cache da página, geralmente deseja manter esses 100 MB na RAM :-). Caso contrário, na melhor das hipóteses você sofrerá atrasos, na pior das hipóteses o sistema passará todo o seu tempo debatendo entre diferentes aplicativos. Então, MemAvailableestá permitindo uma pequena porcentagem de RAM para isso. Pode não permitir o suficiente ou pode ser excessivamente generoso. "O impacto desses fatores variará de sistema para sistema".

Para muitas cargas de trabalho de PC, o argumento sobre "muitos arquivos" pode não ser relevante. Mesmo assim, atualmente tenho 500 MB de memória recuperável em placas no meu laptop (de 8 GB de RAM). Isso ocorre devido a ext4_inode_cache(mais de 300 mil objetos). Aconteceu porque recentemente tive que varrer todo o sistema de arquivos para descobrir o que estava usando meu espaço em disco :-). Eu usei o comando df -x / | sort -n, mas, por exemplo, o Gnome Disk Usage Analyzer faria a mesma coisa.

2. [editar] Memória em grupos de controle

Os chamados "containers Linux" são construídas a partir de namespaces, cgroupse vários outros recursos acordo com o gosto :-). Eles podem fornecer um ambiente convincente o suficiente para executar algo quase como um sistema Linux completo. Os serviços de hospedagem podem criar contêineres como este e vendê-los como "servidores virtuais" :-).

Servidores de hospedagem também podem criar "servidores virtuais" usando recursos que não estão no Linux principal. Os contêineres OpenVZ pré-datam os cgroups da linha principal por dois anos e podem usar "contadores de feijão" para limitar a memória. Portanto, você não pode entender exatamente como esses limites de memória funcionam se você apenas ler documentos ou fazer perguntas sobre o kernel Linux principal. cat /proc/user_beancountersmostra o uso e os limites atuais. vzubcapresenta em um formato um pouco mais amigável. A página principal dos contadores de feijão documenta os nomes das linhas.

Grupos de controle incluem a capacidade de definir limites de memória nos processos dentro deles. Se você executar seu aplicativo dentro desse cgroup, nem toda a memória do sistema estará disponível para o aplicativo :-). Então, como podemos ver a memória disponível neste caso?

A interface para isso difere de várias maneiras, dependendo se você usa cgroup-v1 ou cgroup-v2 .

A instalação do meu laptop usa cgroup-v1. Eu posso correr cat /sys/fs/cgroup/memory/memory.stat. O arquivo mostra vários campos, incluindo total_rss, total_cache, total_shmem. O shmem, incluindo tmpfs, conta para os limites de memória. Eu acho que você pode ver total_rsscomo um equivalente inverso de MemFree. E também há o arquivo memory.kmem.usage_in_bytes, representando a memória do kernel, incluindo lajes. (Presumo que memory.kmem.também inclua memory.kmem.tcp.e quaisquer extensões futuras, embora isso não esteja documentado explicitamente). Não há contadores separados para visualizar a memória recuperável da laje. O documento para cgroup-v1 diz que atingir os limites de memória não aciona a recuperação de nenhuma memória de laje. (O documento também declara que está "irremediavelmente desatualizado" e que você deve verificar o código fonte atual).

O cgroup-v2 é diferente. Eu acho que o cgroup raiz (de nível superior) não suporta contabilidade de memória. O cgroup-v2 ainda possui um memory.statarquivo. Todos os campos somam-se aos cgroups filhos, portanto, você não precisa procurar por total_...campos. Existe um filecampo, o que significa a mesma coisa cache. Irritantemente, não vejo um campo geral como o rssinterior memory.stat; Eu acho que você teria que adicionar campos individuais. Existem estatísticas separadas para memória de laje recuperável e irrecuperável; Eu acho que um cgroup v2 é projetado para recuperar lajes quando começa a ficar com pouca memória.

Os cgroups do Linux não virtualizam automaticamente /proc/meminfo(ou qualquer outro arquivo /proc), de modo que mostrem os valores para toda a máquina. Isso confundiria os clientes VPS. No entanto, é possível usar espaços para nome para substituir /proc/meminfopor um arquivo falsificado pelo software de contêiner específico . A utilidade dos valores falsos dependeria do que esse software específico faz.

systemdacredita que o cgroup-v1 não pode ser delegado com segurança, por exemplo, para contêineres. Eu olhei dentro de um systemd-nspawncontêiner no meu sistema cgroup-v1. Eu posso ver o cgroup em que ele foi colocado e a memória contando com isso. Por outro lado, o contido systemdnão configura os cgroups por serviço comuns para a contabilidade de recursos. Se a contabilidade da memória não foi ativada dentro deste cgroup, presumo que o contêiner não possa ativá-lo.

Suponho que se você estiver dentro de um contêiner cgroup-v2, ele parecerá diferente da raiz de um sistema cgroup-v2 real e você poderá ver a memória representando seu cgroup de nível superior. Ou, se o cgroup que você vê não tiver a contabilidade de memória ativada, esperamos que você receba permissão para poder ativar a contabilidade de memóriasystemd (ou equivalente).

sourcejedi
fonte
1
é clicky nao. Eu uso os links do GitHub porque eles mostram a primeira versão que contém o commit (semelhante a git describe --contains). Encontrou-o vinculado como TL; DR por uma pergunta SU, que acabou de citar a seção adicionada ao proc.txt. Mas para esta pergunta, a descrição do commit é perfeita IMO :-).
sourcejedi
MemAvailable não parece estar disponível na maioria dos servidores virtuais ... o que fazer então?
Roland Seuhs
@RolandSeuhs possivelmente aprende "contadores de feijão". Veja as edições em negrito. Se você tiver uma pergunta sobre contadores de feijão, agradeceria se você fizesse uma nova pergunta. Podemos sempre vincular a ele a partir deste, mas os detalhes provavelmente não são relevantes para qualquer leitor que use um kernel linux da linha principal.
sourcejedi