Optimización del tiempo de recompilación de #[sqlx::test] en proyectos Rust

Fuentes: Optimizing #[sqlx::test] rebuild time

Este artículo analiza por qué los tiempos de recompilación de los tests #[sqlx::test] en proyectos Rust pueden volverse excesivamente lentos y qué soluciones existen. El autor, que mantuvo la suite de tests de integración de bors (el bot de merge queue usado en rust-lang/rust), comprobó que cada cambio obligaba a esperar entre 7,5 y 10 segundos para reconstruir las pruebas, lo que afectaba directamente a su productividad.

La lentitud no se debía a la conexión con la base de datos, ya que compilaba con SQLX_OFFLINE=1, sino a dos factores principales. Primero, el atributo #[sqlx::test] genera, para cada test, código Rust que embebe la lista completa de migraciones con su SQL, descripción y checksum como un array de bytes en forma de constante. En bors, con unos 350 tests y 30 migraciones, el resultado eran 32 MiB de código generado. Segundo, la conversión de los datos de las migraciones a tokens mediante la crate quote durante la ejecución de la macro también consume un tiempo considerable.

El autor comprobó que reducir las migraciones a una sola recortaba el tiempo de 7,5 s a 5 s y el código expandido a 6 MiB. Para mitigarlo, propone parchear sqlx para que la carga de migraciones se haga en tiempo de ejecución (runtime) en lugar de en compilación, generando una llamada a una función que las lea del disco. Esta técnica bajó el tiempo de reconstrucción a unos 5 s y dejó la salida de cargo expand en 6 MiB, sin impacto apreciable en la ejecución de los tests. La caché experimental de proc macros del compilador no ayudó porque el cuello de botella es compilar el código generado, no ejecutar la macro. El artículo señala como inconvenientes que los tests dejan de ser autocontenidos.