El crate `bzip2` cambia de C a una implementación 100% en Rust
(trifectatech.org)- El crate
bzip20.6.0 adopta por defectolibbz2-rs-sys, una implementación en Rust del algoritmo bzip2, eliminando la dependencia de C y mejorando a la vez la velocidad y la facilidad de compilación cruzada - bzip2 es un algoritmo antiguo cuyo uso ha disminuido, pero varios protocolos y bibliotecas todavía deben soportarlo para cumplir con las especificaciones, por lo que sigue presente en lo profundo del árbol de dependencias
- La implementación en Rust usó aproximadamente 9.66~14.87% menos ciclos de CPU que C en compresión, y también mejoró la descompresión en 4.48~10.00% en todas las pruebas
- Al eliminar C, se simplifican los builds para WebAssembly, Windows y Android, y además,
libbz2-rs-sysno exporta símbolos por defecto, reduciendo el riesgo de conflictos de símbolos con otras dependencias - En la auditoría se corrigieron 1 bug lógico de tipo off-by-one y algunas limitaciones del fuzzer, y las bibliotecas y aplicaciones de nivel superior que usan
bzip2ahora también pueden ejecutarse con MIRI
Cambio de implementación predeterminada en bzip2 0.6.0
- El crate
bzip20.6.0 ahora usa por defectolibbz2-rs-sys, una implementación en Rust del algoritmo bzip2 - Al eliminar la dependencia previa de C, el crate
bzip2ahora es más rápido y más fácil de compilar de forma cruzada - El crate
libbz2-rs-systambién puede compilarse como una biblioteca dinámica de C para que los proyectos en C puedan aprovechar estas mejoras - Aunque hoy bzip2 no se usa tanto, muchos protocolos y bibliotecas aún deben soportarlo para cumplir con las especificaciones, y sigue presente en lo profundo del árbol de dependencias de varios proyectos
- Los detalles de la implementación pueden consultarse en la publicación anterior Translating bzip2 with c2rust
Resultados de mejora de rendimiento
- La implementación en Rust generalmente es más rápida que la implementación en C, y en algunos casos ofrece un rendimiento similar
- Dentro de lo conocido, no hay casos realmente más lentos
- En los benchmarks de compresión, se redujeron los ciclos de CPU frente a 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%- El
levelde bzip2 se refiere al uso de memoria de trabajo y no afecta mucho al rendimiento sample3.refasigna más memoria que el tamaño del archivo incluso con level 1, por lo que niveles más altos tienen poca relevancia
- El rendimiento de descompresión también mejoró en todas las pruebas
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%
- En la máquina de benchmarks con macOS, a veces las cifras de rendimiento de descompresión salían más bajas
- No se identificó la causa, y en macOS era difícil hacer funcionar herramientas que automaticen el rastreo de rendimiento como
perf
- No se identificó la causa, y en macOS era difícil hacer funcionar herramientas que automaticen el rastreo de rendimiento como
Build y mitigación de conflictos de símbolos
- La compilación cruzada de proyectos Rust con dependencias en C suele funcionar de inmediato gracias al crate
cc, pero cuando falla puede ser difícil depurar los errores- El enlace con bibliotecas del sistema también puede generar problemas confusos y difíciles de reproducir
- La compilación de bzip2 para WebAssembly llevaba mucho tiempo presentando problemas
- Al eliminar la dependencia en C y usar solo código Rust, los builds para WebAssembly, Windows y Android pasan a ser más fáciles de hacer funcionar
libbz2-rs-sysno exporta símbolos por defecto- Cuando se usa una dependencia en C, hay que exportar símbolos para que los bloques Rust
externpuedan encontrarlos - Los nombres exportados pueden entrar en conflicto si otra dependencia declara los mismos símbolos
- Si un proyecto Rust necesita exportar símbolos, puede activarlo mediante una feature flag
- Cuando se usa una dependencia en C, hay que exportar símbolos para que los bloques Rust
Resultados de validación y auditoría
- Una implementación de bzip2 orientada al rendimiento requiere algo de código unsafe, y replicar en Rust la interfaz de C implica aún más código unsafe
- Ese código puede ejecutarse en MIRI
- Las bibliotecas o aplicaciones de nivel superior que usan
bzip2ahora también pueden ejecutarse con MIRI
- En la auditoría se detectó 1 bug lógico de tipo off-by-one y se corrigieron algunas limitaciones del fuzzer
- Fuera de eso, no hubo hallazgos importantes
- La auditoría estuvo a cargo de Radically Open Security y el informe completo puede consultarse en el PDF del informe de auditoría
- Este trabajo contó con el apoyo de Alex Crichton, mantenedor del crate
bzip2; de Radically Open Security, que aportó la auditoría y su experiencia; y de NLnet Foundation, que lo financió a través de e-Commons Fund
Aún no hay comentarios.