...

HugePages do Linux na hospedagem: um impulso para o MariaDB, o Redis e o PHP-FPM

Vou mostrar concretamente como as hugepages do Linux impulsionam o MariaDB, o Redis e o PHP-FPM na pilha de alojamento, onde causam lentidão e como as configuro de forma específica. É assim que reduzo Latência, reduzir os erros de TLB e manter a Gestão da memória previsível.

Pontos centrais

Os pontos-chave que se seguem resumem os passos e efeitos mais importantes.

  • Modo THP Escolher deliberadamente: „madvise“ para cargas de trabalho gerais, „never“ para serviços sensíveis, como o Redis.
  • HugePages estáticas Prever espaço para grandes conjuntos de buffers do MariaDB, a fim de reduzir a latência e as falhas de TLB.
  • Redis Proteger contra picos de latência: desativar o THP e limitar os custos de bifurcação.
  • PHP-FPM beneficia-se indiretamente de uma menor sobrecarga do kernel e de backends mais rápidos.
  • Avaliação comparativa e realizar o acompanhamento antes da entrada em funcionamento, tornando os efeitos mensuráveis.

HugePages e THP: uma breve explicação

Eu uso Páginas enormes, para ativar páginas de memória maiores e, assim, reduzir o número de páginas a gerir. As páginas clássicas têm 4 KB, enquanto as páginas grandes têm, na maioria das vezes, 2 MB são grandes. Desta forma, as falhas de TLB diminuem significativamente, a CPU gasta menos tempo na gestão da memória e os serviços que requerem muitos acessos à RAM respondem mais rapidamente. Transparent Huge Pages (THP) tenta fazê-lo automaticamente e pode funcionar sem necessidade de ajustes na aplicação. Relatórios práticos mostram frequentemente operações 20–40 % mais rápidas, quando as cargas de trabalho e as configurações estão em sintonia.

Escolher e testar corretamente os modos THP

Faço uma distinção clara entre os modos „sempre“, „madvise“ e „never“, porque afetam as cargas de trabalho de forma diferente. „always“ pode ocupar uma quantidade surpreendente de RAM e gerar esforço de cópia quando os serviços fazem forking. „madvise“ permite controlo: apenas a memória que a aplicação marca explicitamente utiliza páginas grandes. „never“ oferece a máxima previsibilidade, especialmente em serviços com grande utilização de forking, como o Redis. Quem quiser aprofundar o tema pode encontrar informações sobre as oportunidades e as armadilhas aqui: THP: Impulso ou problema. Testo cada modo com carga real, medo a latência, o tempo de CPU e o RSS, e depois tomo uma decisão com base nos factos.

Configuração prática no servidor

Antes de alterar os serviços, asseguro que as predefinições do host sejam reproduzíveis e que exista um plano de contingência seguro.

Configurar o THP de forma específica (parâmetros de arranque ou systemd)

  • Ao arrancar o kernel: adicionar „transparent_hugepage=madvise“ ou „transparent_hugepage=never“ no GRUB e reiniciar o sistema.
  • Em execução através do sysfs – ideal para testes ou numa unidade do systemd:
Verificar o estado do #
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag

# Mudança para madvise (exemplo)
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
echo never   > /sys/kernel/mm/transparent_hugepage/defrag

Guardo estes comandos numa pequena unidade do systemd, para que as reinicializações não percam a configuração.

Reservar HugePages estáticas

No que diz respeito à reserva do lado do HugeTLB, planeio de forma conservadora e com margem de segurança (ver lista de verificação abaixo):

# Verificar o tamanho e o contador
grep -i huge /proc/meminfo

# Reservar 32 GB (páginas de 2 MB -> 16384)
sysctl -w vm.nr_hugepages=16384
echo "vm.nr_hugepages=16384" > /etc/sysctl.d/90-hugepages.conf

# Opcional: Ponto de montagem para o hugetlbfs (útil para diagnóstico)
mkdir -p /dev/hugepages
echo "hugetlbfs /dev/hugepages hugetlbfs defaults,pagesize=2M 0 0" >> /etc/fstab
mount -a

Quando os serviços utilizam o HugeTLB, normalmente necessitam de direitos MEMLOCK. Para tal, defino limites e capacidades na respetiva unidade do systemd:

[Service]
LimitMEMLOCK=infinity
CapabilityBoundingSet=CAP_IPC_LOCK
AmbientCapabilities=CAP_IPC_LOCK

Verificação: os processos utilizam páginas grandes?

Verifico a utilização efetiva de cada processo:

# Totais de AnonHugePages por processo
grep -i 'AnonHugePages' /proc/$PID/smaps | awk '{s+=$2} END {print s " kB"}'

# Indicadores a nível do sistema
grep -i huge /proc/meminfo

MariaDB: ganhos com HugePages estáticas

O MariaDB baseia-se no InnoDB-Pool de buffer e de uma utilização previsível da RAM. Normalmente, configuro o THP para bases de dados produtivas em „nunca“ ou defino-o para „madvise“, caso esteja a realizar testes específicos. Motivo: durante o forking e em cargas de escrita, as páginas de 2 MB geram custos elevados de «copy-on-write», o que atrasa as consultas e prejudica o desempenho do MariaDB. HugePages estáticas para um buffer pool grande e mais orientado para a leitura tornam a latência mais uniforme e reduzem a sobrecarga administrativa. Além disso, ajusto o vm.swappiness e o agendador de E/S para que o kernel não deslocar o buffer desnecessariamente.

Configuração no MariaDB, NUMA e E/S

  • Pool de buffer adequado à carga: innodb_buffer_pool_size como alavanca principal, innodb_buffer_pool_instances para a paralelização.
  • Ativar páginas grandes (se for suportado pela versão): innodb_use_large_pages=ON ou, mais precisamente, „FORCE“ apenas após o teste.
  • Suavizar o percurso de E/S: innodb_flush_method=O_DIRECT, uma estratégia Write-Amp bem definida, pontos de verificação controlados.
  • Evitar armadilhas NUMA: mysqld via numactl --interleave=all iniciar quando houver risco de desequilíbrio nos nós.
  • Limites do sistema: MEMLOCK conforme indicado acima; reservar antecipadamente HugePages em quantidade suficiente para que o arranque não falhe.

Na prática, aumento o buffer pool em incrementos razoáveis (por exemplo, 8 → 16 → 32 GB), observo as taxas de erros de página e comparo a latência 99p. As cargas de trabalho orientadas para a leitura são as que mais beneficiam; em caso de elevada carga de gravação, analiso com especial cuidado os custos de CoW e os ciclos de fsync.

Redis: evitar picos de latência

O Redis é muito sensível ao comportamento da memória e aos custos de fork em Instantâneos e reescritas AOF. Com o THP ativo, o sistema não precisa de mover 4 KB, mas sim 2 MB durante a cópia – trata-se de uma unidade 512 vezes maior, o que provoca picos de latência. Por isso, costumo definir o THP para „nunca“, o que torna a memória do Redis mais previsível. No caso de conjuntos de chave-valor grandes, predominantemente de leitura, posso testar o „madvise“, mas apenas com benchmarks rigorosos. Além disso, defino vm.overcommit_memory=1 e ajusto a desfragmentação do Redis, para manter a fragmentação sob controlo.

Módulos de configuração para custos de bifurcação reduzidos

  • THP: Definir „never“ a nível do host, equilibrar a carga de forks.
  • AOF/Instantâneo: no-appendfsync-on-rewrite yes, aof-rewrite-incremental-fsync yes, definir os horários em função dos períodos de menor tráfego.
  • Desfragmentação: activedefrag sim, ajustar com precisão os limiares (limite-inferior-da-desfragmentação-ativa, controlo de ciclos).
  • Overcommit: vm.overcommit_memory=1, para que os garfos não fiquem encravados.
  • Alocador: Utilizar o Redis com o jemalloc para manter a fragmentação a um nível baixo.

Medo os efeitos com o monitorização de latência integrada do Redis e correlaciono os picos com eventos BGSAVE ou AOF. Se a latência de 99,9p diminuir de forma estável, aplico as configurações no ambiente de produção.

PHP-FPM: impulso indireto na pilha web

O próprio PHP-FPM raramente consome grandes quantidades de RAM, mas beneficia de uma quantidade menor Sobrecarga do kernel e backends mais rápidos. Quando o MariaDB e o Redis respondem mais rapidamente, o TTFB e o tempo de resposta por pedido diminuem. Ajusto o número de trabalhadores do FPM, o `max_children` e o gestor de processos (dinâmico ou estático) de acordo com a curva de carga. Desta forma, aproveito as vantagens das HugePages em todo o sistema, sem correr o risco de avançar às cegas. Aqui, apresento uma introdução prática ao tema: Como utilizar corretamente as HugePages do servidor.

Na prática: parâmetros do processo, Opcache e dimensionamento

  • Calculo o valor de pm.max_children da seguinte forma: (RAM para o PHP) / (RSS médio por worker), com uma reserva de 10–20 %.
  • Manter o cache de códigos de operação estável: suficiente opcache.memory_consumption e opcache.interned_strings_buffer, para evitar recompilações.
  • Consistência do alocador: a utilização das mesmas famílias de alocadores C (glibc/jemalloc) em todos os componentes evita a fragmentação inesperada.
  • O THP „madvise“ no servidor ajuda moderadamente no caso de bibliotecas partilhadas, sem aumentar os custos de bifurcação.

Configuração: passo a passo e tabela resumida

Começo cada mudança com uma Inventário: RAM, taxas de gravação e leitura, comportamento de bifurcação, pico de carga. Em seguida, defino objetivos, como uma latência constante com N pedidos por segundo ou menos tempo de CPU no kernel. Configurei o THP de acordo com cada serviço e realizei testes em condições realistas. Em seguida, registei os resultados e implementei as alterações de forma controlada. A tabela seguinte resume os pontos de partida testados na prática, que posteriormente ajusto com precisão:

Serviço Modo THP HugePages estáticas Nota
MariaDB enlouquecer ou nunca Sim, compatível com o buffer pool Os grandes conjuntos de dados orientados para a leitura beneficiam; é necessário testar cuidadosamente a carga de escrita.
Redis nunca Provavelmente não Evitar custos de bifurcação, manter a desfragmentação ativa.
PHP-FPM enlouquecer Raramente necessário Os benefícios resultam, principalmente, de forma indireta, graças a back-ends mais rápidos.

Ambiente de alojamento: a escolha determina o desempenho

Só consigo alcançar de forma duradoura constante Casos em que o fornecedor configura o kernel e as predefinições de forma adequada. Isto inclui kernels atualizados, predefinições razoáveis do THP, reservas suficientes de RAM e um serviço de apoio com experiência em otimização. Ao comparar produtos de alojamento, presto atenção a informações claras sobre o ajuste do MariaDB, do Redis e do PHP-FPM. Quem quiser compreender as diferenças entre o HugeTLB e o THP pode beneficiar desta introdução concisa: Comparação entre HugeTLB e THP. Em testes, o webhoster.de revelou-se, graças à sua configuração fiável, um forte candidato para projetos com grande volume de dados.

Containers, Cgroups e Kubernetes

Em ambientes de contentores, o meu planeamento é um pouco diferente, uma vez que muitas definições são válidas para todo o host e não podem ser alteradas por pod ou contentor Docker:

  • O THP é uma configuração do host. Eu instalo-o no nó, não no contentor.
  • O HugeTLB requer páginas reservadas no host. Nas orquestrações, atribuo recursos explicitamente (tipos de 2Mi/1Gi por nó) e agendo os pods nessas páginas.
  • Cgroups: Tenho em atenção memória.max/Limites de swap, para que encerramentos imprevistos devido a falta de memória (OOM) não comprometam as séries de medições.
  • Consistência de imagens: versões idênticas do alocador em todos os contentores relevantes, para que a fragmentação não sofra desvios aleatórios.

Estou a realizar testes ao nível dos nós com parâmetros do kernel idênticos e a alternar as implementações de forma rotativa, para evitar picos de carga e caches inativos.

Avaliação comparativa, monitorização e planeamento de capacidade

Não me baseio na intuição, eu medo duro. Antes e depois de cada alteração, utilizo perfis de carga idênticos e registo a latência, o débito, o tempo de CPU no espaço do utilizador e no espaço do kernel, bem como o RSS. Verifico também os picos, e não apenas os valores médios, para poder detetar precocemente valores atípicos. Para o planeamento, utilizo margens de segurança para que o crescimento não atinja imediatamente os limites. Desta forma, mantenho o desempenho constante ao longo de semanas e distribuo as reservas de forma sensata.

Parâmetros de medição e comandos de teste rápidos

  • Estado do THP: cat /sys/kernel/mm/transparent_hugepage/enabled, .../desfragmentar.
  • HugeTLB: grep -i huge /proc/meminfo, cat /proc/sys/vm/nr_hugepages.
  • Do lado do processo: /proc/$PID/smaps para AnonHugePages procurar.
  • Falhas graves/menores e indicadores TLB: perf stat -p $PID -e cycles,task-clock,minor-faults,major-faults,dTLB-load-misses,iTLB-load-misses.
  • Latências do Redis: ferramentas de latência integradas, correlação com BGSAVE/AOF.
  • MariaDB: MOSTRAR ESTADO GLOBAL e esquema de desempenho para taxas de acertos na memória tampão e comportamento dos pontos de verificação do InnoDB.

O que importa é a consistência da campanha de medição: conjuntos de dados idênticos, janelas de teste idênticas, carga de fundo idêntica. Caso contrário, estou a comparar maçãs com peras.

Padrões de erro e soluções rápidas

Se os tempos de resposta aumentarem após a substituição de um switch THP, verifico imediatamente Fork- Eventos e comportamento „Copy-on-Write“. Se houver um aumento de „slow queries“ no MariaDB, reduzo a amplitude de gravação, defino o THP de forma mais conservadora e avalio o percurso de E/S. Se o Redis reportar picos de latência esporádicos, defino o THP para «never» e verifico os momentos de criação de instantâneos. Se a carga da CPU aumentar repentinamente, observo as falhas de TLB indiretamente através dos indicadores do Perf e reduzo o número de HugePages estáticas. Documento cada correção para poder agir mais rapidamente caso a situação se repita.

Estratégia de reversão

  • Redefinir a configuração do THP para o modo anterior; reiniciar apenas se necessário.
  • Reduzir gradualmente as HugePages estáticas (vm.nr_hugepages), não desligar bruscamente.
  • Anular os indicadores específicos do serviço (innodb_use_large_pages, Definições de desfragmentação), e, em seguida, volte a medir.
  • Regista os valores «antes» e «depois», para que a próxima iteração seja mais rápida.

Lista de verificação e cálculo das dimensões

Para o cálculo de estruturas estáticas Páginas enormes Recorro a um cálculo simples: número = tamanho pretendido em bytes dividido pelo tamanho da página (2 MB). Se, por exemplo, pretender um buffer pool InnoDB de 32 GB, preciso de cerca de 16 384 páginas de 2 MB cada. Acrescento uma reserva de 5 a 10 %, para que pequenas flutuações não provoquem estrangulamentos. Depois, verifico no arranque se a instância acede efetivamente a páginas grandes. Se a medição corresponder às expectativas, aplico a configuração a outros nós.

Nota sobre as HugePages de 1 GB

No caso de conjuntos de buffers muito grandes e estáveis, as páginas de 1 GB (HugeTLB, dependendo da CPU/do kernel) aliviar a pressão adicional sobre a TLB. Só as utilizo se as necessidades de memória forem constantes a longo prazo e se houver reservas contínuas suficientemente grandes disponíveis. A configuração segue o mesmo padrão que no caso dos 2 MB, mas requer um planeamento e testes mais rigorosos, uma vez que a fragmentação e o comportamento no arranque são mais sensíveis.

Brevemente resumido

Eu fixo linux Utilizo as hugepages de forma seletiva: o THP normalmente „madvise“ para pilhas Web, „never“ para o Redis e páginas estáticas para grandes conjuntos de MariaDB orientados para a leitura. Desta forma, reduzo as falhas de TLB, mantenho as latências constantes e evito surpresas de memória. O PHP-FPM beneficia indiretamente, uma vez que a base de dados e a cache respondem mais rapidamente. Através de testes de desempenho e monitorização rigorosos, comprovo os efeitos e garanto as alterações. Em combinação com um fornecedor que disponibiliza predefinições modernas do kernel e o suporte adequado, a pilha mantém-se fiável e rápida mesmo sob carga.

Artigos actuais

Servidor Linux com configuração otimizada de HugePages para MariaDB e Redis no centro de dados
Servidores e Máquinas Virtuais

HugePages do Linux na hospedagem: um impulso para o MariaDB, o Redis e o PHP-FPM

Descubra como as HugePages do Linux ajudam a tornar o MariaDB, o Redis e o PHP-FPM mais rápidos e estáveis em ambientes de alojamento. Com foco nas HugePages do Linux, receberá dicas práticas sobre a configuração do THP, o ajuste do kernel e configurações otimizadas para a memória.