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.
linux
linux-kernel
Raghu
fonte
fonte
vmstat
em camposo
?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 :)Respostas:
Estou respondendo à tag linux . 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()
ouposix_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
vmstat
obter uma visão geral do que realmente está sendo armazenado.fonte
Núcleo
Para obter o índice de fragmentação atual, use:
Para desfragmentar a memória do kernel, tente executar:
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
.fonte
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.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.
fonte
Existe o
/proc/buddyinfo
que é 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:
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=4G
opçã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.
fonte