
Uma tradução do artigo foi preparada para os alunos do curso Linux Administrator .
Anteriormente, falei sobre como testar e habilitar o uso de Hugepages no Linux.
Este artigo será útil apenas se você realmente tiver onde usar as páginas enormes. Eu conheci muitas pessoas que são enganadas pela perspectiva de que o Hugepages aumentará magicamente a produtividade. No entanto, páginas enormes é um tópico complexo e, se usado incorretamente, pode reduzir o desempenho.
Parte 1: verifique se páginas enormes estão incluídas no Linux (original aqui )
Problema:
Você precisa verificar se o HugePages está ativado no seu sistema.
Solução:
É bem simples:
cat /sys/kernel/mm/transparent_hugepage/enabled
Você obterá algo como isto:
always [madvise] never
Você verá uma lista de opções disponíveis ( sempre, madvise, nunca ), enquanto a opção ativa atual será colocada entre colchetes (por padrão, madvise ).
madvise significa que páginas enormes transparent hugepages
são incluídas apenas para regiões de memória que solicitam explicitamente páginas enormes com madvise (2) .
sempre significa que grandes transparent hugepages
estão sempre ativadas para todos os processos. Isso geralmente melhora o desempenho, mas se você tiver um caso de uso em que muitos processos consomem uma pequena quantidade de memória, a carga total de memória pode aumentar drasticamente.
Nunca significa que grandes transparent hugepages
não serão incluídas, mesmo quando solicitadas usando o madvise. Veja a documentação do kernel do Linux para mais informações .
Como alterar o valor padrão
Opção 1 : Altere o sysfs
diretamente (após a reinicialização, o parâmetro será revertido para o valor padrão):
echo always >/sys/kernel/mm/transparent_hugepage/enabled echo madvise >/sys/kernel/mm/transparent_hugepage/enabled echo never >/sys/kernel/mm/transparent_hugepage/enabled
Opção 2 : Altere o padrão do sistema recompilando o kernel com a configuração modificada (esta opção é recomendada apenas se você usar seu próprio kernel):
Parte 2: Vantagens e desvantagens do HugePages
Tentaremos explicar seletivamente as vantagens, desvantagens e possíveis erros ao usar o Hugepages. Como o artigo tecnologicamente sofisticado e pedante provavelmente será difícil para as pessoas que são enganadas ao considerar as Hugepages uma panacéia, sacrificarei a precisão por uma questão de simplicidade. Vale lembrar que muitos tópicos são realmente complexos e, portanto, bastante simplificados.
Observe que estamos falando de sistemas x86 de 64 bits em execução no Linux, e que apenas assumo que o sistema suporta páginas grandes e transparentes (já que não é uma desvantagem que páginas grandes não sejam substituídas), como acontece em quase todos os sistemas modernos. Ambiente Linux.
Nos links abaixo, anexarei uma descrição mais técnica.
Memória virtual
Se você é um programador C ++, sabe que os objetos na memória têm endereços específicos (valores do ponteiro).
No entanto, esses endereços não refletem necessariamente os endereços físicos na memória (endereços na RAM). Eles são endereços na memória virtual. O processador possui um módulo MMU (unidade de gerenciamento de memória) especial que ajuda o kernel a mapear a memória virtual para um local físico.
Essa abordagem tem muitas vantagens, mas a mais básica delas:
- Desempenho (por várias razões);
- Isolamento de programas, ou seja, nenhum dos programas pode ler da memória de outro programa.
O que são páginas?
A memória virtual é dividida em páginas. Cada página individual aponta para uma memória física específica, para uma região na RAM ou para um endereço atribuído a um dispositivo físico, como uma placa de vídeo.
A maioria das páginas com as quais você lida aponta para RAM ou troca, ou seja, elas são armazenadas no seu disco rígido ou SSD. O kernel controla o layout físico de cada página. Se uma página falsificada for acessada, o kernel interrompe o thread que está tentando acessar a memória, lê a página do disco rígido / SSD na RAM e continua a executar o thread.
Esse processo é transparente para o fluxo, ou seja, não é necessariamente lido diretamente no disco rígido / SSD. O tamanho das páginas normais é 4096 bytes. Páginas enormes têm 2 megabytes de tamanho.
Buffer de tradução associativa (TLB)
Quando um programa acessa uma página de memória, o processador central deve saber de qual página física ler os dados (ou seja, ter um mapa de endereço virtual).
O núcleo possui uma estrutura de dados (tabela de páginas) que contém todas as informações sobre as páginas usadas. Usando essa estrutura de dados, você pode mapear um endereço virtual para um endereço físico.
No entanto, a tabela de páginas é bastante complexa e é executada lentamente, portanto, simplesmente não podemos analisar toda a estrutura de dados cada vez que um processo acessa a memória.
Felizmente, nosso processador possui um TLB que armazena em cache o mapeamento de endereços virtuais e físicos. Isso significa que, apesar de precisarmos analisar a tabela de páginas na primeira tentativa de obter acesso, todas as chamadas de páginas subsequentes podem ser processadas no TLB, o que garante uma operação rápida.
Como é implementado como um dispositivo físico (o que o torna principalmente rápido), sua capacidade é limitada. Portanto, se você quiser acessar mais páginas, o TLB não poderá armazenar o mapeamento para todas elas, como resultado do qual seu programa funcionará muito mais devagar.
Páginas enormes vêm em socorro
Então, o que podemos fazer para evitar o excesso de TLB? (Supomos que o programa ainda precise da mesma quantidade de memória).
É aqui que as páginas enormes aparecem. Em vez de 4096 bytes, exigindo apenas uma entrada no TLB, uma entrada no TLB agora pode apontar para 2 megabytes impressionantes. Assumiremos que o TLB possui 512 entradas, aqui sem Hugepages podemos corresponder:
4096 b⋅512=2 MB
Enquanto com eles podemos comparar:
2 MB⋅512=1 GB
É por isso que o Hugepages é incrível. Eles podem aumentar a produtividade sem um esforço significativo. Mas existem reservas significativas.
Hugepages spoofing
O kernel rastreia automaticamente a frequência de uso de cada página da memória. Se a memória física (RAM) for insuficiente, o kernel moverá as páginas menos importantes (usadas com menos frequência) para o disco rígido para liberar parte da RAM para páginas mais importantes.
Basicamente, o mesmo vale para Hugepages. No entanto, o kernel pode trocar apenas páginas inteiras, não bytes individuais.
Suponha que tenhamos um programa como este:
char* mymemory = malloc(2*1024*1024); // Hugepage! // mymemory - // , // mymemory // ... // putchar(mymemory[0]);
Nesse caso, o kernel precisará substituir (ler) até 2 megabytes de informações do disco rígido / SSD apenas para você ler um byte. Quanto às páginas comuns, apenas 4096 bytes precisam ser lidos no disco rígido / SSD.
Portanto, se uma página enorme for substituída, sua leitura será mais rápida apenas se você precisar acessar a página inteira. Isso significa que, se você estiver tentando acessar aleatoriamente diferentes partes da memória e apenas ler alguns kilobytes, use páginas regulares e não se preocupe com mais nada.
Por outro lado, se você precisar acessar a maior parte da memória sequencialmente, páginas enormes aumentarão sua produtividade. No entanto, você precisa verificar isso sozinho (e não no exemplo de software abstrato) e ver o que funciona mais rápido.
Alocação de memória
Se você escreve em C, sabe que pode solicitar quantidades arbitrariamente pequenas (ou quase arbitrariamente grandes) de memória do heap usando malloc()
. Digamos que você precise de 30 bytes de memória:
char* mymemory = malloc(30);
Pode parecer ao programador que você "solicita" 30 bytes de memória do sistema operacional e retorna um ponteiro para alguma memória virtual. Mas, na verdade, malloc ()
é apenas uma função C que chama as funções brk e sbrk de dentro para solicitar ou liberar memória do sistema operacional.
No entanto, solicitar cada vez mais memória para cada alocação é ineficiente; é mais provável que qualquer segmento de memória já tenha sido liberado (free())
, e podemos reutilizá-lo. malloc()
implementa algoritmos bastante complexos para reutilizar a memória liberada.
Ao mesmo tempo, tudo passa despercebido para você, então por que isso deveria preocupá-lo? Mas porque a chamada para free()
não significa que a memória será retornada imediatamente para o sistema operacional .
Existe uma fragmentação de memória. Em casos extremos, existem segmentos de heap nos quais apenas alguns bytes são usados, enquanto tudo o que foi intermediário foi liberado (free())
.
Observe que a fragmentação da memória é um tópico incrivelmente complexo, e mesmo pequenas alterações no programa podem afetá-lo significativamente. Na maioria dos casos, os programas não causam fragmentação significativa da memória, mas lembre-se de que, se ocorrer fragmentação em alguma área da pilha, grandes páginas poderão agravar a situação.
Aplicação personalizada de enormes páginas
Depois de ler o artigo, você determinou quais partes do seu programa podem se beneficiar do uso de grandes páginas e quais não. Então, enormes páginas devem ser incluídas?
Felizmente, você pode usar o madvise()
para ativar páginas enormes apenas em áreas da memória onde elas serão úteis.
Para começar, verifique se as páginas grandes funcionam no modo madvise (), usando as instruções no início do artigo.
Então, use madvise()
para dizer ao kernel exatamente onde usar páginas enormes.
#include <sys/mman.h> // , size_t size = 256*1024*1024; char* mymemory = malloc(size); // hugepages… madvise(mymemory, size, MADV_HUGEPAGE); // … madvise(mymemory, size, MADV_HUGEPAGE | MADV_SEQUENTIAL)
Observe que esse método é apenas uma recomendação para o kernel para gerenciamento de memória. Isso não significa que o kernel utilizará automaticamente páginas enormes para a memória fornecida.
Consulte a página de manual madvise para obter mais informações sobre gerenciamento de memória e madvise()
, uma curva de aprendizado incrivelmente íngreme para este tópico. Portanto, se você realmente entender bem, prepare-se para ler e testá-lo por várias semanas antes de contar com pelo menos algum resultado positivo.
O que ler?
Tem uma pergunta? Escreva nos comentários!