Fragmentação de memória Linux

20

Existe uma maneira de detectar a fragmentação da memória no linux? Isso ocorre porque em alguns servidores de execução demorada eu notei uma degradação do desempenho e somente depois que reinicio o processo, vejo um desempenho melhor. Percebi mais ao usar o suporte a grandes páginas do linux - as grandes páginas no linux são mais propensas à fragmentação?

Eu olhei para / proc / buddyinfo em particular. Quero saber se existem maneiras melhores (não apenas os comandos da CLI em si, qualquer programa ou fundamentação teórica) para analisar.

Raghu
fonte
Não estou olhando apenas soluções rápidas de linha de comando, qualquer programa / teoria simples também funcionará. Portanto, eu não perguntei no serverfault.
Raghu
11
Eu não entendo aqui um ponto. Tanto quanto eu entendo, a fragmentação da memória deve levar à falta de memória e, como resultado, a erros de alocação de memória. No entanto, você está perguntando sobre a degradação do desempenho. É porque você tem muita memória trocada para o disco? E se sim, o que dá vmstatem campo so?
@skwllsp - Editei minha resposta para ser mais específico.
Tim Post
@Raghu - Eu não esperaria que a maioria dos administradores de sistema modificasse o código do kernel para fazer com que o gerenciamento de memória se comportasse de maneira diferente; no entanto, administradores especializados do Linux devem saber pelo menos uma visão geral de como o Linux gerencia a memória. Esta questão está realmente em jogo. Votei em migrar simplesmente porque não posso sugerir (na minha resposta) código que responda à sua pergunta. Ler / proc ou usar vmstaté uma experiência comum do usuário. Se você estivesse escrevendo um programa para fazer o mesmo, seria diferente. Se você pretende usar o bash para colher esta informação, editar a sua pergunta, não vai ser fechado :)
Tim Publicar
@ Tim - Como sugeri, não são apenas os comandos bash / cli que eu queria saber, eu precisava das informações para me ajudar no meu procedimento de benchmarking (para analisar os resultados, não para executá-los).
Raghu

Respostas:

12

Estou respondendo à tag . Minha resposta é específica apenas para Linux .

Sim, páginas grandes são mais propensas a fragmentação. Existem duas visões de memória, a que seu processo obtém (virtual) e a que o kernel gerencia (real). Quanto maior a página, mais difícil será agrupar (e mantê-la) seus vizinhos, especialmente quando o serviço estiver sendo executado em um sistema que também precisa oferecer suporte a outros que, por padrão, alocam e gravam em muito mais memória do que eles. na verdade, acabam usando.

O mapeamento do kernel de endereços concedidos (reais) é privado. Há uma boa razão pela qual o espaço do usuário os vê como o kernel os apresenta, porque o kernel precisa ser capaz de se comprometer demais sem confundir o espaço do usuário. Seu processo obtém um espaço de endereço "Disneyfied" agradável e contíguo no qual trabalhar, alheio ao que o kernel está realmente fazendo com essa memória nos bastidores.

A razão pela qual você vê desempenho degradado em servidores de longa execução é mais provável porque os blocos alocados que não foram explicitamente bloqueados (por exemplo, mlock()/ mlockall()ou posix_madvise()) e que não foram modificados por um tempo foram paginados , o que significa que seu serviço desliza para o disco quando é necessário ler eles. A modificação desse comportamento torna seu processo um vizinho ruim , e é por isso que muitas pessoas colocam seus RDBMS em um servidor completamente diferente de web / php / python / ruby ​​/ qualquer que seja. A única maneira de corrigir isso, de maneira sutil, é reduzir a competição por blocos contíguos.

A fragmentação só é realmente perceptível (na maioria dos casos) quando a página A está na memória e a página B mudou para troca. Naturalmente, reiniciar seu serviço parece 'curar' isso, mas apenas porque o kernel ainda não teve a oportunidade de paginar o processo '(agora) os blocos recém-alocados dentro dos limites de sua taxa de supercomprometimento.

De fato, reiniciar (digamos) 'apache' sob uma carga alta provavelmente enviará blocos pertencentes a outros serviços diretamente ao disco. Então sim, o 'apache' melhoraria por um curto período de tempo, mas o 'mysql' poderá sofrer .. pelo menos até que o kernel os faça sofrer da mesma forma quando houver simplesmente uma falta de memória física suficiente.

Adicione mais memória ou divida os malloc()consumidores exigentes :) Não é apenas uma fragmentação que você precisa observar.

Tente vmstatobter uma visão geral do que realmente está sendo armazenado.

Tim Post
fonte
Obrigado pela resposta. Eu estava usando páginas enormes (tamanho = 2048 KB cada) para o mysql - pool de buffers innodb - para ver quão bem ele se sai (usando o sysbench). Inicialmente, quando o tempo de atividade do processo (e até o tempo de atividade do sistema) era baixo, ele apresentava resultados muito bons. No entanto, seu desempenho começou a diminuir em várias execuções. Com relação à página que você mencionou, certamente notei uma atividade alta da VM, mas presumi que isso possa ter ocorrido devido ao fluxo de benchmark e ao innodb (atividade vm maior com páginas grandes do que sem). Também configurei vm.swappiness como 1. Não pude notar nenhuma mudança drástica.
Raghu
De acordo com o manual , "Páginas enormes não podem ser trocadas sob pressão de memória". Acho que essa é uma boa resposta na memória padrão w / r / t, mas não para páginas grandes.
Dan Pritts 28/03
5

Núcleo

Para obter o índice de fragmentação atual, use:

sudo cat /sys/kernel/debug/extfrag/extfrag_index

Para desfragmentar a memória do kernel, tente executar:

sysctl vm.compact_memory=1  

Além disso, você tenta desativar as Páginas grandes transparentes (também conhecidas como THP) e / ou desativar a troca (ou diminuir swappiness).

Espaço do usuário

Para reduzir a fragmentação do espaço do usuário, você pode tentar um alocador diferente, por exemplo jemalloc(ele possui ótimos recursos de introspecção , o que lhe dará uma visão interna da fragmentação interna do alocador).

Você pode mudar para o malloc personalizado recompilando seu programa com ele ou apenas executando o programa com LD_PRELOAD: LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app (cuidado com as interações entre o THP e os alocadores de memória )

Embora um pouco não relacionado à fragmentação da memória (mas conectado à compactação / migração da memória), você provavelmente deseja executar várias instâncias do seu serviço, uma para cada nó NUMA e vinculá-las usando numactl.

SaveTheRbtz
fonte
11
Por que você acha que desativar a troca poderia ajudar? Para mim, parece mais provável que desabilitar a troca doerá ainda mais.
kasperd
11
Como não há informações suficientes na postagem original, talvez o processo esteja apenas vazando e comece a trocar. Também não vejo razões legítimas para o uso de swap em praticamente qualquer sistema de produção (mb apenas para estações de trabalho compartilhadas para estudantes).
SaveTheRbtz
2
Ter espaço de troca suficiente melhorará o desempenho. Os problemas de desempenho que você terá se tiver espaço de troca insuficiente é motivo suficiente para ativar a troca.
kasperd
11
@SaveTheRbtz Uma boa razão para usar swap em um sistema de produção é que ele oferece ao sistema mais opções que ele usará apenas se achar que são benéficas. Além disso, permite que páginas modificadas que não foram acessadas em horas (e que nunca podem ser acessadas) sejam ejetadas da preciosa memória física. Por fim, ele permite que o sistema lide com segurança com casos em que muito mais memória é reservada do que usada.
David Schwartz
2
"somente se achar que são benéficos" - isso adiciona heurística adicional e torna o sistema menos previsível. Também algoritmos de substituição de página (usados ​​em swap e anônimo mmap) são implementados de maneira diferente em kernels diferentes (por exemplo, Linux vs FreeBSD), ou mesmo versões diferentes do mesmo sistema operacional (2.6.32 vs 3.2 vs 3.10) .. "permite páginas modificadas [. para ser ejetado da [...] memória física "- que ocultará vazamentos de memória. "lida com casos em que muito mais memória é reservada do que é usada" - o sistema lento é muito pior do que o sistema inativo, portanto, "são" é questionável.
SaveTheRbtz
4

O uso de páginas grandes não deve causar fragmentação extra de memória no Linux; O suporte do Linux a páginas grandes é apenas para memória compartilhada (via shmget ou mmap), e quaisquer páginas grandes usadas devem ser especificamente solicitadas e pré-localizadas por um administrador do sistema. Uma vez na memória, eles são fixados lá e não são trocados. O desafio de trocar páginas enormes em face da fragmentação da memória é exatamente o motivo pelo qual elas permanecem fixadas na memória (ao alocar uma página enorme de 2 MB, o kernel deve encontrar 512 páginas 4KB gratuitas contíguas, que podem até não existir).

Documentação do Linux em grandes páginas: http://lwn.net/Articles/375098/

Há uma circunstância em que a fragmentação da memória pode fazer com que a alocação enorme de páginas seja lenta (mas não onde páginas grandes causam fragmentação da memória), e se o sistema estiver configurado para aumentar o pool de páginas enormes, se solicitado por um aplicativo. Se / proc / sys / vm / nr_overcommit_hugepages for maior que / proc / sys / vm / nr_hugepages, isso poderá acontecer.

jstultz
fonte
De fato - e geralmente deve ajudar o desempenho, porque evitará falhas no TLB (consulte o artigo vinculado para explicação).
Dan Pritts
0

Existe o /proc/buddyinfoque é muito útil. É mais útil com um bom formato de saída, como este script Python pode fazer:

https://gist.github.com/labeneator/9574294

Para páginas grandes, você deseja alguns fragmentos gratuitos no tamanho 2097152 (2MiB) ou superior. Para páginas enormes e transparentes, ele será compactado automaticamente quando o kernel for solicitado, mas se você quiser ver quantas pode obter, execute o root:

echo 1 | sudo tee /proc/sys/vm/compact_memory

Além disso, sim, páginas enormes causam grandes problemas de fragmentação. Você não pode obter páginas enormes, ou a presença delas faz com que o kernel gaste muito tempo extra tentando obter algumas.

Eu tenho uma solução que funciona para mim. Eu o uso em alguns servidores e no meu laptop. Funciona muito bem para máquinas virtuais.

Adicione a kernelcore=4Gopção à sua linha de comando do kernel do Linux. No meu servidor eu uso 8G. Tenha cuidado com o número, pois isso impedirá que seu kernel aloque qualquer coisa fora dessa memória. Servidores que precisam de muitos buffers de soquete ou que transmitem gravações de disco para centenas de unidades não gostam de ficar limitados assim. Qualquer alocação de memória que precise ser "fixada" para laje ou DMA está nesta categoria.

Toda a sua outra memória torna-se "móvel", o que significa que pode ser compactada em blocos agradáveis ​​para grande alocação de página. Agora, páginas enormes e transparentes podem realmente decolar e funcionar como deveriam. Sempre que o kernel precisa de mais 2 milhões de páginas, ele pode simplesmente remapear as páginas em 4K para outro lugar.

E não tenho muita certeza de como isso interage com o IO direto de cópia zero. A memória na "zona móvel" não deve ser fixada, mas uma solicitação de E / S direta faria exatamente isso no DMA. Pode copiá-lo. Pode fixá-lo na zona móvel de qualquer maneira. Em ambos os casos, provavelmente não é exatamente o que você queria.

Zan Lynx
fonte