3 pontos por GN⁺ 2025-06-19 | 1 comentários | Compartilhar no WhatsApp
  • O crate bzip2 substituiu a dependência de código C por uma implementação 100% Rust
  • O desempenho melhorou de forma geral em relação à versão anterior, e a compilação cruzada ficou mais fácil
  • A implementação em Rust melhora tanto a velocidade de compressão quanto a de descompressão em comparação com a versão em C
  • Problemas de dependência de bibliotecas, como conflitos de símbolos, foram bastante reduzidos
  • Após uma auditoria de segurança, bugs importantes de lógica foram corrigidos, validando a estabilidade

Lançamento do bzip2 crate 0.6.0 e transição para Rust

  • Hoje foi lançado o bzip2 versão 0.6.0
  • Agora ele usa por padrão o libbz2-rs-sys, uma implementação do algoritmo bzip2 em Rust desenvolvida internamente
  • Com essa transição, o crate bzip2 ficou mais rápido e a compilação cruzada se tornou mais simples
  • O crate libbz2-rs-sys também pode ser compilado como uma biblioteca dinâmica em C. Com isso, projetos em C também podem aproveitar as melhorias de desempenho

Por que essa transição aconteceu?

  • O algoritmo bzip2 foi criado nos anos 90 e hoje não é mais tão amplamente usado, mas ainda é necessário em vários protocolos e bibliotecas para conformidade com especificações
  • Muitos projetos dependem do bzip2, não diretamente, mas em algum ponto profundo da árvore de dependências
  • Com base na experiência acumulada com o zlib-rs, desta vez modernizamos a implementação do bzip2
  • Os detalhes de implementação do crate libbz2-rs-sys foram tratados em um post anterior do blog. Aqui, veremos os benefícios desta transição

Desempenho melhorado

  • De forma geral, a implementação em Rust mostra desempenho superior ao da versão em C
  • Em alguns casos o desempenho é equivalente, mas não há situações em que ela seja mais lenta
  • Desempenho de compressão: no bzip2 existe a opção level, mas o impacto no desempenho é mínimo
  • Nos testes, a versão em Rust mostrou ganho de velocidade de mais de 10% em arquivos de amostra representativos

Compressão:

Arquivo C(ciclos de execução) Rust(ciclos de execução) Variação relativa
sample3.ref (level 1) 38.51M 33.53M -14.87%
silesia-small.tar (level 1) 3.43G 3.00G -14.30%
silesia-small.tar (level 9) 3.47G 3.17G -9.66%

Na descompressão também houve melhora de desempenho em todos os casos:

Arquivo C(ciclos de execução) Rust(ciclos de execução) Variação relativa
sample3.bz2 2.53M 2.42M -4.48%
sample1.bz2 9.63M 8.86M -8.63%
sample2.bz2 20.47M 19.02M -7.67%
dancing-color.ps.bz2 87.46M 83.16M -5.17%
re2-exhaustive.txt.bz2 1.89G 1.76G -7.65%
zip64support.tar.bz2 2.32G 2.11G -10.00%

No entanto, no ambiente macOS, às vezes ocorrem variações nos números de descompressão. Foi difícil analisar isso por limitações das ferramentas de medição de desempenho

Suporte a compilação cruzada

  • Em projetos Rust com dependências em C, a compilação cruzada normalmente funciona bem graças ao crate cc, mas quando falha é muito difícil depurar
  • No processo de linkedição com bibliotecas de sistema, é fácil surgirem problemas inesperados, e em alguns ambientes — incluindo builds para WebAssembly — isso se torna um obstáculo real
  • Ao migrar para a implementação em Rust, os problemas relacionados a C desaparecem completamente
  • Agora é possível fazer compilação cruzada para Windows, Android, WebAssembly e outros ambientes sem particularidades
  • Isso é uma grande vantagem não só para a experiência do usuário, mas também do ponto de vista de manutenção

Sem conflitos de símbolos(export) por padrão

  • No caso de dependências em C, é necessário exportar símbolos em blocos externos ao Rust, então há conflito quando outra dependência exporta os mesmos símbolos
  • O libbz2-rs-sys foi projetado para não exportar símbolos por padrão
  • Por isso, não há risco de conflito de símbolos com outras bibliotecas externas. Se necessário, também é possível ativar a exportação via feature flag

Execução de testes com MIRI

  • Para implementar o bzip2 com alto desempenho em Rust, o uso de código unsafe é inevitável, e também é necessário bastante unsafe para reproduzir a interface em C
  • Felizmente, agora é possível executar e testar esse código no ambiente MIRI
  • Além disso, bibliotecas ou aplicações de nível superior que usam bzip2 agora também passam a poder ser testadas com MIRI

Conclusão

Agora, o crate bzip2 está mais rápido. A experiência melhora naturalmente, a ponto de ser algo com que você nem precisa mais se preocupar

1 comentários

 
GN⁺ 2025-06-19
Comentários no Hacker News
  • Considerando a possibilidade de a implementação da Trifecta Tech substituir a implementação oficial usada por distribuições Linux, isso não parece impossível, já que no passado o Fedora trocou o Adler zlib tradicional pelo zlib-ng. A opinião é que o ponto principal é oferecer uma C ABI compatível com a original
    • Se não houve lançamento upstream desde 2019, surge a dúvida se essa implementação não estaria simplesmente pronta. Se não há mais bugs para corrigir nem recursos para adicionar, talvez isso por si só já seja suficiente
    • Como o Ubuntu usa um sudo escrito em Rust, esse tipo de troca parece perfeitamente plausível
    • A Trifecta Tech está oferecendo bem uma C ABI compatível, mas no fim alguém precisa realmente executar esse trabalho para que a mudança aconteça
    • Também foi mencionado que o objetivo do uutils é esse tipo de substituição oficial, com compartilhamento do link da página do uutils
    • Numa olhada rápida, já existe configuração de cargo-c, o que parece positivo, mas como o namespace é diferente, programas em C não detectariam automaticamente como se fosse a libbz2 existente. Como não há familiaridade com os símbolos do bzip2, é difícil saber o grau exato de compatibilidade ABI. Manter pessoalmente uma implementação do sistema operacional GNU consome muito tempo, então PRs são bem-vindos no projeto experimental platypos quando houver tempo
  • Estou usando esse crate para processar centenas de TB de dados do Common Crawl. A posição é de grande satisfação porque a velocidade aumentou
    • Foi levantada a pergunta sobre por que usar bz2 nesse caso. Para uma conversão grande feita só uma vez, ouvi dizer que migrar para zstd traz muita vantagem, e foi apresentada a ideia de que, quanto maior a taxa de compressão, melhor ele é que o bzip2 em praticamente tudo
    • Houve a pergunta se os dados do Common Crawl são disponibilizados em formato torrent
    • A impressão compartilhada é que uma melhora de 14% na velocidade de compressão é muito boa
  • Há curiosidade se essa implementação resolve por padrão os 11 CVEs ainda pendentes. Ironicamente, foi dito que o crate bzip2 também teve CVEs reportados, com compartilhamento deste link relacionado
    • Foi considerada interessante a comparação entre vulnerabilidades do tipo “falha em tempo de execução com arquivos grandes” reportadas nesse crate e problemas de bounds miss em implementações em C. Fica a dúvida se esse tipo de vulnerabilidade por violação de limites poderia de fato levar à execução de código
    • Foi citada a orientação de que “o crate bzip2 é vulnerável em versões anteriores à 0.4.4”. Informação adicional: hoje saiu a versão 0.6.0
  • Em resposta à pergunta “por que melhorar um algoritmo dos anos 90?”, houve interesse em saber quais algoritmos são usados hoje em dia. Foi mencionado o zstd, com compartilhamento deste link de benchmark comparando algoritmos de compressão
  • Há curiosidade sobre como ocorre ganho de velocidade se o backend de codegen dos compiladores de C e Rust for o mesmo. Foram levantadas várias possibilidades, como auto-SIMD do Rust, otimizações manuais ou uso de novas bibliotecas de otimização
    • A suposição é que Rust pode fornecer mais pistas ao gerador de código. Como exemplo, diferentemente dos ponteiros em C, haveria menos preocupação com problemas de aliasing. Foi compartilhado este link explicando aliasing
    • A opinião é que a linguagem C não é realmente boa para escrever código moderno de alto desempenho. Foi apontado que, de C99 a C21, ao longo de cerca de 20 anos, a própria linguagem careceu de recursos para aproveitar de forma elegante novas instruções como clz, popcnt, clmul, pdep etc. A avaliação é que esse tipo de suporte a instruções abstratas já ajuda muito na otimização desse tipo de código
    • Reescrever em qualquer linguagem pode abrir oportunidades de ganho de desempenho, e isso não seria uma garantia exclusiva do Rust
  • Existe a esperança de que a Nana ou a Prossimo reescrevam de forma semelhante implementações centrais de protocolos da internet (BGP, OSPF, RIP etc.), além de servidores DNS
    • Foram apresentados links para fundos que, nos últimos anos, vêm apoiando a reescrita em Rust e outras linguagens seguras de ferramentas centrais da internet e do sistema operacional: o projeto NLnet e o Sovereign Tech Fund. Como exemplo, também foi citado o projeto BGP in Rust
    • A Memory Safety Initiative apresenta esforços de reescrita segura de serviços centrais como TLS e DNS, o que coincide em parte com essa proposta
    • Foi mencionado que um desenvolvedor criou o Ironsides DNS em SPARK Ada, linguagem que oferece provas formais mais fortes
  • No macOS, mesmo sem o profiler perf, parece que o dtrace já é suficiente para análise de desempenho. O script original de flame graph, escrito em Perl, também usava dtrace, e a reimplementação em Rust do flame graph segue a mesma abordagem. Faltam algumas métricas, como cache miss ou micro instruction retired, mas ainda assim continua muito útil
  • Houve um comentário em tom de piada dizendo que agora falta reescrever Rust em Javascript
  • Foi perguntado se há suporte a descompressão paralela, como no lbzip2. Ou então se seria possível paralelizar com algo como pré-varredura de block magic. Em uma edição posterior, a conclusão foi “provavelmente não suporta”
  • Foi compartilhada a experiência de que o Lbzip2 mostrava velocidade de descompressão muito alta ao usar todos os núcleos da CPU. A lamentação é que, mesmo em 2025, muitos programas importantes, como Python, ainda usam apenas um núcleo
    • Foi apontado que essa avaliação sobre a situação do Python não está muito clara