Introdução ao RCU
- O sistema operacional é, no dia a dia, um dos programas mais sensíveis a desempenho.
- Um sistema operacional sempre pode ser mais rápido, e desenvolvedores de kernel e drivers se dedicam à otimização de código.
- Um sistema operacional exige concorrência em larga escala, escalonando processos e threads em espaço de usuário, além de ter suas próprias threads e tratadores de interrupção que interagem com o hardware.
Como o RCU funciona
- Quando é preciso alterar atomicamente dados lidos com frequência, mas escritos raramente (por exemplo, dispositivos USB atualmente conectados), usa-se a estratégia RCU (Read, Copy, Update).
- Lê-se os dados, faz-se uma cópia para modificá-los e então atualiza-se atomicamente o ponteiro para a nova versão.
- Esse método é fácil de usar e não tem espera, mas pode causar vazamentos de memória.
Resolvendo o problema de vazamento de memória
- Para evitar vazamentos de memória, em vez de excluir os dados antigos dentro da função de atualização, é possível adiar a exclusão até que não haja mais leitores acessando-os.
- Assim, gerencia-se a memória com segurança fazendo o escritor esperar para excluir os dados enquanto os leitores ainda estão lendo.
Uso prático do RCU
- O RCU é usado dezenas de milhares de vezes no Linux, além de aparecer na biblioteca C++ Folly, do Facebook, e no
crossbeam-epoch de Rust.
- O RCU é motivado por requisitos de desempenho e latência, oferecendo uma forma de gerenciamento de memória semelhante à coleta de lixo.
Equívocos sobre coleta de lixo
- A noção comum de que coleta de lixo é mais lenta do que gerenciamento manual de memória desmorona rapidamente quando se observam os detalhes.
- A função
free() não é gratuita, e o alocador de memória precisa manter internamente bastante estado.
- Coletores de lixo modernos oferecem otimizações como movimentação e coleta geracional, proporcionando alta vazão e bom desempenho de cache.
A ilusão de controle
- Às vezes, desenvolvedores querem construir sistemas de tempo real, mas na prática não têm controle perfeito sobre o gerenciamento de memória.
- O sistema operacional apenas tenta inferir a intenção do desenvolvedor em relação à alocação de memória, e às vezes um simples acesso a ponteiro pode se transformar em I/O de disco.
Conclusão
- Nem todo software se beneficia de coleta de lixo, mas ela é uma ferramenta útil e não deveria mais ser temida, nem mesmo entre programadores de sistemas.
Opinião do GN⁺
- O RCU é uma técnica eficaz para aumentar a concorrência mantendo a consistência dos dados em ambientes multithread. Isso é um elemento muito importante em computação de alto desempenho e sistemas de tempo real.
- O exemplo do RCU, que quebra noções preconcebidas sobre coleta de lixo, oferece aos desenvolvedores uma nova perspectiva sobre gerenciamento de memória. Isso vale ainda mais na área de programação de sistemas, em que o gerenciamento de memória é especialmente importante.
- Outros projetos que oferecem funcionalidades semelhantes ao RCU incluem o ConcurrentLinkedQueue do Java e o ConcurrentBag do .NET, que também fornecem estruturas de dados lock-free.
- Ao adotar a tecnologia RCU, é preciso considerar os requisitos do sistema e os objetivos de desempenho, entendendo os benefícios obtidos com seu uso e também seus custos potenciais.
- Este artigo pode ajudar desenvolvedores a compreender melhor gerenciamento de memória e concorrência, reconsiderar pressupostos existentes e explorar novas soluções.
1 comentários
Comentários do Hacker News
Sugestão para conferir as técnicas inovadoras de coleta de lixo paralela (GC) do MPL e do MaPLe
disentanglementbaseado em coleta de lixo paralela comprovadamente eficienteÉ interessante usar RCU como motivação para coleta de lixo
Equívocos gerais sobre gerenciamento de memória
O caso de uso de RCU é convincente, mas a experiência com coleta de lixo em outras situações não é boa
free()devolve memória ao SOAo usar coleta de lixo, novas alocações passam a ocorrer na RAM, e não no cache
Uma boa coleta de lixo por rastreamento supera há muito tempo o gerenciamento manual de memória em termos de throughput
Uma das coisas que combinam bem com coleta de lixo é async/await
Depois da motivação com RCU, é um pouco surpreendente mudar para uma discussão sobre coleta de lixo em geral
Ao desenvolver software, consideram-se dois casos
A transição de RCU para coleta de lixo por rastreamento em geral parece uma estratégia astuta
É difícil para programadores de sistemas identificar quando algo pode ser coletado pelo garbage collector
As ferramentas de gerenciamento de ciclo de vida do Rust e do C++ ajudam a automatizar a liberação de memória, mas não simplificam a complexidade