CRAM: Como o Linux pode eliminar o custo do zram e zswap

Escrito por
Emanuel Negromonte
Emanuel Negromonte é Jornalista, Mestre em Tecnologia da Informação e atualmente cursa a segunda graduação em Engenharia de Software. Com 14 anos de experiência escrevendo sobre...

O fim do overhead de swap na gestão de memória!

Dispositivos de hardware que realizam compressão de memória transparente apresentam um desafio estrutural para o kernel Linux: eles reportam uma capacidade lógica superior à sua capacidade física real. Quando a taxa de compressão esperada não é atingida, o sistema operacional continua alocando endereços virtuais para páginas físicas inexistentes. Para resolver essa assimetria de informações sem depender do subsistema tradicional de paginação, desenvolvedores apresentaram o Compressed RAM Service (CRAM), uma arquitetura que mantém os dados mapeados para leitura direta e evita o custo computacional dos page faults.

O problema da capacidade percebida

O kernel Linux gerencia a memória assumindo uma correspondência direta entre a alocação lógica e o espaço físico disponível. Em dispositivos com compressão por hardware, essa relação é rompida. A estrutura struct page pode acabar apontando para espaços vazios se os dados armazenados não puderem ser comprimidos na proporção esperada.

Nesse cenário, o mecanismo de recuperação de memória (reclaim) falha ao ser acionado. Como o kernel acredita que ainda há espaço disponível com base na capacidade lógica reportada, a alocação de páginas continua ininterruptamente até o esgotamento físico do dispositivo, desestabilizando o sistema. O CRAM introduz um controle de alocação estrito, garantindo que o kernel seja informado da restrição física e inicie o reclaim no momento correto.

A limitação do subsistema de swap

JTH1aFFY cram linux memoria comprimida sem overhead swap 1
CRAM: Como o Linux pode eliminar o custo do zram e zswap 3

A abordagem padrão para lidar com compressão de memória no Linux envolve ferramentas como zswap ou zram, que operam sob a infraestrutura de swap. Nesses modelos, as páginas comprimidas são desmapeadas (PROT_NONE). Qualquer tentativa de acesso exige a alocação de uma nova página e a descompressão dos dados, gerando obrigatoriamente um swap-in fault.

Medições realizadas pelo desenvolvedor Kairui Song indicam que a descompressão do dado não é o principal gargalo. O tempo gasto na descompressão LZO é de aproximadamente 0,32 microssegundo por página, enquanto o gerenciamento do page fault direto consome cerca de 1,92 microssegundo e a infraestrutura de swap exige 1,04 microssegundo adicional. O CRAM contorna esse custo mantendo a memória residente no sistema. Em testes com cargas exclusivas de leitura, a arquitetura registrou zero swap-in faults, tornando a performance comparável à da DRAM convencional.

Controle de gravação e promoção de páginas

A velocidade dos links de comunicação coerentes (como o CXL) permite taxas de transferência na ordem de gigabytes por segundo. Se um processo realizar gravações massivas diretamente na memória comprimida, a rotina de reclaim não conseguirá liberar espaço físico com rapidez suficiente, gerando uma sobrecarga severa capaz de paralisar o sistema.

Para evitar esse cenário, o CRAM implementa um controle rigoroso baseado na política “Promote on Write”. As páginas migradas para a camada CRAM recebem permissões exclusivas de leitura (R/O PTE) para memória anônima. A leitura ocorre diretamente do dispositivo. No entanto, qualquer tentativa de gravação aciona um mecanismo de promoção, movendo a página imediatamente de volta para a DRAM padrão antes que a modificação seja consolidada, limitando o impacto do tempo de compressão.

Implementação via nó NUMA e gerenciamento de capacidade

O design do CRAM isola o dispositivo criando um nó NUMA privado para o hardware de compressão. A transferência de dados entre as camadas ocorre por meio da API de migração de páginas do kernel (utilizando funções como migrate_pages e cram_migrate_to), evitando o caminho de código do swap-out tradicional.

A arquitetura também aplica a técnica de ballooning para redimensionamento dinâmico e inclui um mecanismo interno no driver para bloquear explicitamente novas alocações. Quando o dispositivo atinge seu limite físico real, esse bloqueio impede a entrada de novos dados, forçando o kernel a redirecionar as requisições ou acionar o processo de mitigação de esgotamento de memória (OOM).

Desempenho comparativo e testes de estresse

A estratégia de manter as páginas mapeadas resulta em um ganho de desempenho substancial. Em um ambiente de teste com 36 GB de memória física para abrigar 46 GB de memória anônima sem operações de gravação, o CRAM alcançou 321 milhões de operações por segundo (ops/s) em um padrão de acesso enviesado (zipf 0.99) e 489 milhões de ops/s em um padrão aleatório uniforme. No mesmo cenário, o módulo zram tradicional atingiu apenas 9,7 milhões de ops/s e 1,1 milhão de ops/s, respectivamente.

Mesmo em cenários adversos, com 20% das operações dedicadas à gravação (acionando a rotina de promoção de volta à DRAM), o CRAM apresentou uma taxa de transferência de 5 a 37 vezes superior à do zram. A sobrecarga de swap no zram foi elevada o suficiente para causar o encerramento do processo por falta de memória (OOM-killed) em testes de estresse com 10% e 20% de gravações no padrão zipf, enquanto o CRAM manteve a operação estável com interrupções totais significativamente menores.

Compartilhe este artigo
Emanuel Negromonte é Jornalista, Mestre em Tecnologia da Informação e atualmente cursa a segunda graduação em Engenharia de Software. Com 14 anos de experiência escrevendo sobre GNU/Linux, Software Livre e Código Aberto, dedica-se a descomplicar o universo tecnológico para entusiastas e profissionais. Seu foco é em notícias, tutoriais e análises aprofundadas, promovendo o conhecimento e a liberdade digital no Brasil.