- Introducción a una estrategia para agregar Rust de forma gradual en servidores Non-Rust (JavaScript, Python, Java, etc.)
- El objetivo es identificar funciones críticas con cuellos de botella de CPU que no cumplen los requisitos de rendimiento y reemplazarlas con implementaciones en Rust
- La estrategia se divide por Tier (nivel de adopción de Rust): Tier 0 no usa Rust y el último Tier reescribe todo el servidor en Rust
Estrategia
Tier 0: Sin Rust
- Implementación de un endpoint de generación de códigos QR en un servidor Node.js
- Rendimiento base: 1464 solicitudes por segundo, latencia promedio de 68 ms, latencia p99 de 96 ms, tamaño promedio de respuesta de 1506 bytes, memoria de 1353 MB
Tier 1: Herramienta CLI en Rust
- Reescritura de la función de generación de códigos QR en Rust y compilación como herramienta CLI
- El servidor host invoca la herramienta CLI
- Rendimiento frente a la base: solicitudes por segundo 1.76 veces mayores, latencia promedio reducida a 0.57 veces, tamaño promedio de respuesta reducido a 0.52 veces, memoria reducida a 0.92 veces
Tier 2: Módulo Wasm en Rust
- La función en Rust se compila como módulo Wasm y el servidor host la carga y ejecuta usando un runtime de Wasm
- El servidor Node.js usa
wasm-bindgen
- Rendimiento frente a la base: solicitudes por segundo 2.03 veces mayores, latencia promedio reducida a 0.50 veces
- Explicación de cómo escribir manualmente los bindings de Wasm (para usuarios de otros lenguajes)
Tier 3: Función nativa en Rust
- La función se escribe en Rust, se compila a código nativo y se carga y ejecuta en el runtime host
- Node.js usa
napi-rs
- Rendimiento frente a la base: solicitudes por segundo 3.75 veces mayores, latencia promedio reducida a 0.26 veces
Tier 4: Reescritura en Rust
- Reescritura de todo el servidor host en Rust
- En la práctica, lo más realista es reescribir solo una parte del servidor host
- Rendimiento frente a la base: solicitudes por segundo 4.93 veces mayores, latencia promedio reducida a 0.21 veces, memoria reducida a 0.01 veces (13 MB de uso)
Conclusión
- Todas las estrategias son buenas, pero Tier 3 es la más efectiva
- Si puedes usar una biblioteca generadora de bindings lista para usar, escribir funciones nativas en Rust es sencillo y tiene un gran impacto en el rendimiento
4 comentarios
Oh........ he estado haciendo varias cosas como todólogo y terminé usando ambos un poco, así que es información sumamente útil.
Últimamente he estado viendo Rust. Es un artículo interesante.
Es un artículo bastante bueno. Este es un ejemplo de cómo usar Rust correctamente.
Parece que Rust sí se está volviendo claramente popular en áreas que antes se resolvían con C/C++.