- En la comunidad de Rust aparece con frecuencia la pregunta: si los hilos pueden hacer todo lo que
async/await puede hacer y además son más simples, ¿por qué elegir async/await?
- Rust es un lenguaje de bajo nivel y no oculta la complejidad de las corrutinas. Esto contrasta con lenguajes como Go, donde todo se vuelve asíncrono por defecto sin que el programador tenga que pensar en ello.
- Los programadores inteligentes intentan evitar la complejidad, así que ¿por qué es necesario
async/await?
Conocer el contexto
- Rust es un lenguaje de bajo nivel. El código suele ser lineal: cuando una tarea termina, se ejecuta otra.
- Cuando se necesita ejecutar muchas tareas al mismo tiempo, como en un servidor web, el código lineal genera problemas.
- La web en sus inicios intentó resolver este problema introduciendo hilos.
- Con hilos es posible atender a varios clientes al mismo tiempo, pero los programadores querían llevar la concurrencia del espacio del sistema operativo al espacio de usuario.
El problema de los timeouts
- Una de las mayores fortalezas de Rust es su composabilidad.
async/await permite aplicar esa composabilidad a funciones I/O-bound.
- Por ejemplo, si se quiere agregar un timeout a una función que atiende a un cliente, puede implementarse usando dos combinadores.
Hilos temáticos
- En un ejemplo basado en hilos, implementar un timeout no es tan sencillo.
TcpStream tiene las funciones set_read_timeout y set_write_timeout, pero su uso es limitado.
- Se presenta una forma de programar timeouts usando combinadores de Rust, pero está limitada a
TcpStream y requiere llamadas adicionales al sistema.
Casos de éxito de async
- El ecosistema HTTP adoptó
async/await como su principal mecanismo de runtime.
tower es un ejemplo de la potencia de async/await, ya que ofrece timeouts, rate limiting, balanceo de carga y más.
macroquad es un motor de juegos en Rust que ejecuta el motor usando async/await.
Mejorar la imagen de Async
- Como las ventajas de
async no son ampliamente conocidas, algunas personas pueden malinterpretarlo.
- La comunidad de Rust tiende a sobrevalorar las ventajas de rendimiento de
async Rust y a minimizar sus beneficios realmente significativos.
async/await debe verse como un modelo de programación potente que permite expresar de forma concisa patrones que en Rust síncrono no pueden representarse sin decenas de hilos y canales.
Opinión de GN⁺
async/await aumenta la complejidad del código al manejar concurrencia, pero al mismo tiempo ofrece la capacidad de atender eficientemente a muchos clientes simultáneamente.
- Este artículo subraya que
async/await tiene fortalezas en el modelo de programación que van más allá de las simples ventajas de rendimiento.
- En Rust,
async/await aporta composabilidad para diversas tareas de I/O, lo que resulta especialmente útil en áreas como servicios de red o servidores web.
- Desde una mirada crítica, la complejidad de
async/await puede convertirse en una barrera de entrada para desarrolladores principiantes, por lo que se requiere un esfuerzo educativo para superarla.
- Otros proyectos que ofrecen funcionalidades similares incluyen la implementación de
async/await en Node.js y la biblioteca asyncio de Python, que también proporcionan un paradigma parecido.
- Al adoptar
async/await, es importante considerar la complejidad y la mantenibilidad del código; aun así, cuando se necesita atender a muchos clientes al mismo tiempo, este modelo ofrece grandes ventajas.
1 comentarios
Comentarios en Hacker News
Async/await y un solo hilo
Mutexestándar y los canalescrossbeam-channelno son justos.Async/await vs. hilos
Problemas del artículo
Puntos que no se trataron
Puntos importantes sobre la cancelación
futures.Una campaña de marketing alrededor de async/await
Async/await vs. fibras
futuresen cualquier momento conlleva un costo grande.Principales ventajas de async/await en Rust
Malentendidos sobre async/await
Razones para elegir async/await en lugar de hilos