Comparando los tiempos de compilación de Rust y C++
(quick-lint-js.com)Leí un artículo interesante en otro sitio y quería compartirlo.
Rust y C++ suelen compararse en varios aspectos. Sin embargo, ha sido difícil comparar directamente los tiempos de compilación porque es raro que el mismo proyecto esté escrito en ambos lenguajes. quick-lint-js informó que comparó los tiempos de compilación después de reescribir parte de un proyecto hecho en C++ en Rust. Eso sí, Windows quedó fuera del entorno de compilación.
Criterios para la migración
- Excluir bibliotecas de terceros
- Trabajo en Linux y macOS
- Suite de pruebas amplia
- FFI, punteros, contenedores estándar y propios, clases y funciones utilitarias, I/O, concurrencia, genéricos, macros, SIMD, herencia, ...
Conclusión
- El tiempo de compilación de Rust es similar al de C++ o más lento (al menos en este proyecto)
- Rust requiere escribir más código que C++
- En la compilación completa (Full), C++ es similar o más rápido
- En la compilación incremental (Incremental), a veces es más corta y a veces más larga (incluso puede ser mucho más larga)
- Decidieron no migrar el resto de quick-lint-js a Rust (¿si hubiera mejoras en el tiempo de compilación quizá lo harían?)
4 comentarios
Parece que también hay muchas personas que usan Rust en nuestro país. Me da curiosidad saber en qué industrias trabajan todos.
Después de la primera compilación, si en C++ modificas archivos
.cppindividuales en lugar de headershcon muchas dependencias, la compilación termina muy rápido; me da curiosidad saber cómo es en Rust.En la sección de preguntas frecuentes de la documentación de Rust explican esto con bastante detalle, así que lo comparto.
====================================
Parece que Rust compila lento. ¿Por qué pasa eso?
Porque traduce el código a lenguaje máquina y lo optimiza. Rust ofrece abstracciones de alto nivel que se compilan a código máquina eficiente, y ese proceso de traducción inevitablemente toma tiempo, sobre todo cuando se aplican optimizaciones.
Aun así, los tiempos de compilación de Rust no son tan malos como podría parecer, y hay motivos para creer que seguirán mejorando. Si se comparan proyectos de tamaño similar en C++ y Rust, por lo general el tiempo para compilar el proyecto completo es parecido. La principal razón por la que Rust puede sentirse más lento es que C++ y Rust tienen modelos de compilación distintos: en C++ la unidad de compilación es un archivo, mientras que en Rust es un crate compuesto por varios archivos. Por eso, durante el desarrollo, cambiar un solo archivo en C++ puede reducir mucho más el tiempo de compilación que en Rust. Actualmente está en marcha un gran trabajo de refactorización del compilador de Rust para hacer posible la compilación incremental, y cuando esté terminado, los tiempos de compilación en Rust también mejorarán de una manera más parecida al modelo de C++.
Aparte del modelo de compilación, en el diseño del lenguaje Rust hay varios elementos que afectan el tiempo de compilación.
Primero, Rust tiene un sistema de tipos relativamente complejo, y necesita dedicar una cantidad no despreciable de tiempo de compilación a hacer cumplir las restricciones que permiten que Rust sea seguro en tiempo de ejecución.
Segundo, el compilador de Rust arrastra deuda técnica antigua y, en particular, la calidad del LLVM IR que genera no es muy buena, por lo que LLVM tiene que invertir tiempo en “arreglarlo”. En el futuro, es posible que las etapas de optimización y traducción basadas en MIR reduzcan la carga que el compilador de Rust le impone a LLVM.
Tercero, que Rust use LLVM para la generación de código es un arma de doble filo. Gracias a LLVM, Rust ofrece un rendimiento en tiempo de ejecución de primer nivel, pero LLVM es un framework enorme que no está enfocado en el tiempo de compilación y es especialmente vulnerable a entradas de baja calidad.
Por último, la estrategia de Rust de monomorphise tipos genéricos de forma similar a C++ produce código rápido, pero tiene el problema de que necesita generar bastante más código que otras estrategias de traducción. Esta expansión de código puede compensarse usando objetos de trait para intercambiar ventajas y desventajas con el despacho dinámico.
Lo que sí es seguro es que los proyectos de Rust devoran muchísimo disco al compilar. Recuerdo que me sorprendió ver que un proyecto que usaba más de cien bibliotecas de pronto ya ocupaba como 2 GB...