crate `bzip2` passa a usar implementação 100% em Rust no lugar de C
(trifectatech.org)- O crate
bzip20.6.0 adota por padrãolibbz2-rs-sys, uma implementação em Rust do algoritmo bzip2, removendo a dependência de C e melhorando ao mesmo tempo o desempenho e a facilidade de cross-compilation - O bzip2 é um algoritmo antigo, hoje menos usado, mas vários protocolos e bibliotecas ainda precisam oferecer suporte para cumprir especificações, por isso ele continua presente em partes profundas da árvore de dependências
- A implementação em Rust usou cerca de 9,66~14,87% menos ciclos de CPU do que a versão em C na compressão, e também melhorou a descompressão em 4,48~10,00% ao longo dos testes
- Com a remoção de C, os builds para WebAssembly, Windows e Android ficam mais simples, e por padrão
libbz2-rs-sysnão exporta símbolos, reduzindo também o risco de conflito de símbolos com outras dependências - Na auditoria, foram corrigidos 1 bug lógico de off-by-one e algumas limitações do fuzzer, e bibliotecas e aplicações de nível superior que usam
bzip2também passaram a poder ser executadas com MIRI
Mudança da implementação padrão no bzip2 0.6.0
- O crate
bzip20.6.0 passa a usar por padrãolibbz2-rs-sys, uma implementação em Rust do algoritmo bzip2 - Ao remover a dependência anterior em C, o crate
bzip2fica mais rápido e mais fácil de cross-compilation - O crate
libbz2-rs-systambém pode ser compilado como uma biblioteca dinâmica em C, permitindo que projetos em C aproveitem essas melhorias - Embora o bzip2 não seja muito usado hoje, muitos protocolos e bibliotecas ainda precisam suportá-lo para cumprir especificações, e ele continua presente em partes profundas da árvore de dependências de vários projetos
- Os detalhes da implementação podem ser vistos no post anterior Translating bzip2 with c2rust
Resultados de melhoria de desempenho
- A implementação em Rust geralmente é mais rápida que a implementação em C, e em alguns casos fica em nível semelhante ao desempenho em C
- Dentro do que se conhece, não há casos realmente mais lentos
- Nos benchmarks de compressão, houve redução nos ciclos de CPU em relação ao C
sample3.reflevel 1:38.51M→33.53M, -14.87%silesia-small.tarlevel 1:3.43G→3.00G, -14.30%silesia-small.tarlevel 9:3.47G→3.17G, -9.66%- O
leveldo bzip2 indica o uso de memória de trabalho e não tem grande impacto no desempenho sample3.refjá aloca mais memória do que o tamanho do arquivo apenas com level 1, então levels mais altos têm pouca relevância
- O desempenho de descompressão também melhorou em todos os testes
sample3.bz2: -4.48%sample1.bz2: -8.63%sample2.bz2: -7.67%dancing-color.ps.bz2: -5.17%re2-exhaustive.txt.bz2: -7.65%zip64support.tar.bz2: -10.00%
- Na máquina de benchmark com macOS, às vezes os números de desempenho de descompressão aparecem mais baixos
- A causa não foi identificada, e no macOS era difícil fazer ferramentas de rastreamento de desempenho como o
perffuncionarem de forma automatizada
- A causa não foi identificada, e no macOS era difícil fazer ferramentas de rastreamento de desempenho como o
Build e mitigação de conflito de símbolos
- Em projetos Rust com dependência de C, a cross-compilation muitas vezes funciona de imediato graças ao crate
cc, mas quando falha pode ser difícil depurar o erro- O link com bibliotecas de sistema também pode gerar problemas confusos e difíceis de reproduzir
- A compilação de bzip2 para WebAssembly já apresentava problemas havia muito tempo
- Ao remover a dependência em C e usar apenas código Rust, os builds para WebAssembly, Windows e Android passam a funcionar com mais facilidade
libbz2-rs-syspor padrão não exporta símbolos- Quando se usa dependência em C, é necessário exportar símbolos para que blocos Rust
externconsigam encontrá-los - Nomes exportados podem entrar em conflito quando outra dependência declara os mesmos símbolos
- Se um projeto Rust precisar exportar símbolos, isso pode ser ativado com uma feature flag
- Quando se usa dependência em C, é necessário exportar símbolos para que blocos Rust
Resultados de verificação e auditoria
- Uma implementação de bzip2 com bom desempenho precisa de algum código unsafe, e reproduzir em Rust a interface em C exige ainda mais código unsafe
- Esse código pode ser executado no MIRI
- Bibliotecas ou aplicações de nível mais alto que usam
bzip2agora também podem ser executadas com MIRI
- Na auditoria, foi encontrado 1 bug lógico de off-by-one e algumas limitações do fuzzer foram corrigidas
- Fora isso, não houve descobertas importantes
- A auditoria foi conduzida pela Radically Open Security, e o relatório completo está disponível no PDF do relatório de auditoria
- Este trabalho contou com a ajuda de Alex Crichton, mantenedor do crate
bzip2, da Radically Open Security, que forneceu auditoria e expertise, e da NLnet Foundation, que financiou o projeto por meio do e-Commons Fund
Ainda não há comentários.