Suponha que um programa peça alguma memória, mas não haja memória livre suficiente. Existem várias maneiras diferentes de o Linux responder. Uma resposta é selecionar alguma outra memória usada, que não foi acessada recentemente, e mover essa memória inativa para swap.
No entanto, vejo muitos artigos e comentários que vão além disso. Eles dizem que mesmo quando há uma grande quantidade de memória livre, o Linux às vezes decide escrever memória inativa para trocar. Gravar para swap com antecedência significa que, quando eventualmente quisermos usar essa memória, não teremos que esperar por uma gravação no disco. Eles dizem que esta é uma estratégia deliberada para otimizar o desempenho.
Eles estão certos? Ou isso é um mito? Cite sua(s) fonte(s).
Por favor, entenda esta questão usando as seguintes definições:
- troca
- memória livre - a memória "livre" exibida pelo comando free . Este é o
MemFree
valor de/proc/meminfo
./proc/meminfo
é um arquivo de texto virtual fornecido pelo kernel. Consulte proc(5) ou documentos do RHEL . - mesmo quando há uma grande quantidade de memória livre - para fins de argumento, imagine que há mais de 10% de memória livre.
Referências
Aqui estão alguns termos de pesquisa: linux "troca oportunista" OU (trocar "quando o sistema não tem nada melhor para fazer" OU "quando não tem nada melhor para fazer" OU "quando o sistema está ocioso" OU "durante o tempo ocioso")
No segundo resultado mais alto do Google, um usuário do StackExchange pergunta "Por que usar swap quando há espaço livre mais do que suficiente na RAM?" e copia os resultados do free
comando mostrando cerca de 20% de memória livre. Em resposta a esta pergunta específica, vejo que esta resposta é altamente votada:
O Linux começa a trocar antes que a RAM seja preenchida. Isso é feito para melhorar o desempenho e a capacidade de resposta:
O desempenho é aumentado porque às vezes a RAM é melhor usada para cache de disco do que para armazenar memória de programa. Portanto, é melhor trocar um programa que está inativo por um tempo e, em vez disso, manter os arquivos usados com frequência no cache.
A capacidade de resposta é melhorada pela troca de páginas quando o sistema está ocioso, em vez de quando a memória está cheia e algum programa está sendo executado e solicitando mais RAM para concluir uma tarefa.
A troca diminui a velocidade do sistema, é claro - mas a alternativa à troca não é não trocar, é ter mais RAM ou usar menos RAM.
O primeiro resultado no Google foi marcado como uma duplicata da pergunta acima :-). Nesse caso, o autor da pergunta copiou os detalhes mostrando 7 MemFree
GB de 16 GB. A pergunta tem uma resposta aceita e votada:
Trocar apenas quando não há memória livre é apenas o caso se você definir
swappiness
como 0. Caso contrário, durante o tempo ocioso, o kernel fará a troca de memória. Ao fazer isso, os dados não são removidos da memória, mas uma cópia é feita na partição swap.Isso significa que, se ocorrer uma situação de esgotamento da memória, ela não precisará gravar no disco imediatamente. Neste caso, o kernel pode apenas sobrescrever as páginas de memória que já foram trocadas, para as quais ele sabe que possui uma cópia dos dados.
O
swappiness
parâmetro basicamente apenas controla o quanto ele faz isso.
A outra citação não afirma explicitamente que os dados trocados também são retidos na memória. Mas parece que você preferiria essa abordagem, se estiver trocando mesmo quando tiver 20% de memória livre, e o motivo pelo qual está fazendo isso é melhorar o desempenho.
Até onde eu sei, o Linux suporta manter uma cópia dos mesmos dados na memória principal e no espaço de troca.
Também notei a alegação comum de que "troca oportunista" acontece "durante o tempo ocioso". Entendo que isso deve ajudar a me tranquilizar de que esse recurso geralmente é bom para o desempenho. Não incluo isso na minha definição acima, porque acho que já tem detalhes suficientes para fazer uma boa pergunta clara. Eu não quero tornar isso mais complicado do que precisa ser.
Motivação original
atop mostra `swout` (troca) quando tenho gigabytes de memória livre. Por quê?
Existem alguns relatórios como este, de Linux escrevendo para trocar quando há muita memória livre. A "troca oportunista" pode explicar esses relatórios. Ao mesmo tempo, pelo menos uma causa alternativa foi sugerida. Como primeiro passo para analisar as possíveis causas: O Linux alguma vez executa "troca oportunista" conforme definido acima?
No exemplo que relatei, a pergunta já foi respondida. A causa não foi a troca oportunista.
O Linux não faz "troca oportunista" conforme definido nesta pergunta.
As seguintes referências primárias não mencionam o conceito:
Mais especificamente:
Com base no exposto, não esperamos nenhuma troca quando o número de páginas gratuitas for maior que a "marca d'água alta".
Em segundo lugar, isso nos diz que o objetivo
kswapd
é criar mais páginas gratuitas.Quando
kswapd
grava uma página de memória para trocar, ela imediatamente libera a página de memória. kswapd não mantém uma cópia da página trocada na memória .Linux 2.6 usa o " rmap " para liberar a página. No Linux 2.4, a história era mais complexa. Quando uma página era compartilhada por vários processos, o kswapd não conseguia liberá-la imediatamente. Isso é história antiga. Todas as postagens vinculadas são sobre Linux 2.6 ou superior.
Esta citação descreve um caso especial: se você configurar o
swappiness
valor como0
. Nesse caso, também não devemos esperar nenhuma troca até que o número de páginas de cache tenha caído para a marca d'água alta. Em outras palavras, o kernel tentará descartar quase todo o cache de arquivos antes de iniciar a troca. (Isso pode causar lentidão enorme. Você precisa ter algum cache de arquivo! O cache de arquivo é usado para armazenar o código de todos os seus programas em execução :-)Quais são as marcas d'água?
As citações acima levantam a questão: Qual é o tamanho das reservas de memória de "marca d'água" no meu sistema? Resposta: em um sistema "pequeno", as marcas d'água de zona padrão podem chegar a 3% da memória. Isso se deve ao cálculo da marca d'água "min". Em sistemas maiores as marcas d'água serão uma proporção menor, aproximando-se de 0,3% da memória.
Portanto, se a pergunta for sobre um sistema com mais de 10% de memória livre, os detalhes exatos dessa lógica de marca d'água não são significativos.
As marcas d'água para cada "zona" individual são mostradas em
/proc/zoneinfo
, conforme documentado em proc(5) . Um extrato do meu zoneinfo:As "marcas d'água" atuais são
min
,low
ehigh
. Se um programa pedir memória suficiente para reduzirfree
abaixomin
de , o programa entrará em "recuperação direta". O programa é feito para esperar enquanto o kernel libera memória.Queremos evitar a recuperação direta, se possível. Então, se
free
cair abaixo dalow
marca d'água, o kernel acordakswapd
.kswapd
libera memória trocando e/ou descartando caches, até quefree
esteja acimahigh
novamente.Qualificação adicional:
kswapd
também será executado para proteger a quantidade total de lowmem_reserve, para uso de kernel lowmem e DMA. O lowmem_reserve padrão é cerca de 1/256 dos primeiros 4GiB de RAM (zona DMA32), portanto, geralmente é em torno de 16MiB.Confirmações de código Linux
código Linux
Às vezes, afirma-se que mudar
swappiness
para0
desativará efetivamente a "troca oportunista". Isso fornece uma via interessante de investigação. Se houver algo chamado "troca oportunista" e puder ser ajustado por troca, podemos persegui-lo encontrando todas as cadeias de chamadas que lêemvm_swappiness
. Observe que podemos reduzir nosso espaço de pesquisa assumindo queCONFIG_MEMCG
não está definido (ou seja, "cgroups de memória" estão desabilitados). A cadeia de chamadas vai:shrink_node_memcg
é comentado "Esta é uma página básica por nó mais livre. Usada tanto pelo kswapd quanto pela recuperação direta". Ou seja, esta função aumenta o número de páginas livres . Ele não está tentando duplicar páginas para trocar para que possam ser liberadas muito mais tarde. Mas mesmo se descontarmos isso:A cadeia acima é chamada a partir de três funções diferentes, mostradas abaixo. Como esperado, podemos dividir os sites de chamada em recuperação direta versus kswapd. Não faria sentido realizar "trocas oportunistas" em recuperação direta.
Assim, presumivelmente, a alegação é que o kswapd é ativado de alguma forma, mesmo quando todas as alocações de memória estão sendo satisfeitas imediatamente a partir da memória livre. Examinei os usos de
wake_up_interruptible(&pgdat->kswapd_wait)
, e não estou vendo nenhum despertar como este.Não, não existe troca oportunista no Linux. Passei algum tempo analisando o problema e todas as fontes (livros didáticos, e-mails nas listas de e-mail dos desenvolvedores do kernel, código-fonte do Linux e comentários de commit, e algumas trocas no Twitter com Mel Gorman) estão me dizendo a mesma coisa: o Linux apenas recupera memória em resposta a alguma forma de pressão de memória (com a exceção óbvia da hibernação).
Todos os equívocos populares sobre o assunto provavelmente derivam do simples fato de que o Linux não pode esperar até o último byte de memória livre antes de iniciar a troca. Ele precisa de algum tipo de almofada para protegê-lo de formas extremas de esgotamento de memória, e existem alguns ajustes que podem afetar o tamanho dessa almofada (por exemplo
vm.min_free_kbytes
, ). Mas não é o mesmo que "trocar porque não há nada melhor para fazer".Infelizmente, o algoritmo de recuperação de quadros de página tornou-se muito mais complexo em relação ao 2.6 (quando foi descrito em detalhes no livro de Mel Gorman), mas a ideia básica é mais ou menos a mesma: a recuperação de página é desencadeada por alocações com falha, que então acordar
kswapd
ou tentar liberar páginas de forma síncrona (dependendo da pressão da memória, sinalizadores de alocação e outros fatores).A razão mais óbvia pela qual as alocações de página podem começar a falhar com memória livre suficiente restante é que elas podem estar solicitando memória contígua enquanto, na realidade, a memória pode estar muito fragmentada para satisfazer a solicitação. Historicamente, os desenvolvedores do kernel do Linux fizeram um grande esforço para evitar a necessidade de alocações contíguas. No entanto, alguns drivers de dispositivo ainda exigem isso - ou porque eles não podem fazer E/S de memória de várias páginas (DMA de dispersão de coleta), ou pode ser apenas uma codificação desleixada pelos desenvolvedores de drivers. O advento das Transparent Huge Pages (THP) forneceu outro motivo para alocar memória em blocos fisicamente contíguos.
A compactação de zona, que foi introduzida no mesmo período, deve ajudar com o problema de fragmentação de memória, mas nem sempre produz o efeito esperado.
Existem vários
vmscan
pontos de rastreamento que podem ajudar a entender exatamente o que está acontecendo em seu caso específico - é sempre mais fácil encontrar o que você precisa no código do kernel do Linux ao ter pilhas de chamadas específicas, em vez de apenas verificar tudo que parece remotamente relevante.