El concepto de coroutine suena muy interesante, pero no sé si tiene sentido en un entorno productivo real. ¿Qué son los casos de uso para corutinas, que se pueden resolver de forma más elegante, más simple o más eficiente que con otros métodos?¿Qué son casos de uso para una corrutina?
Respuesta
Las corutinas verdaderas requieren soporte de sus herramientas; deben ser implementadas por el compilador y respaldadas por el marco subyacente.
Un ejemplo del mundo real de Coroutines se encuentra con la palabra clave "yield return" proporcionada en C# 2.0, que le permite escribir un método que devuelve múltiples valores para el bucle.
El "rendimiento de retorno" tiene limitaciones, sin embargo, la implementación utiliza una clase auxiliar para capturar el estado, y solo admite un caso específico de coroutine como generador (iterador).
En el caso más general, la ventaja de corrutinas es que hacen ciertos cálculos basados estado mucho más fáciles de expresar y más fácil de entender - implementar una máquina de estado como un conjunto de co-rutinas pueden ser más elegante que los enfoques más comunes . Pero hacer esto requiere soporte y herramientas que aún no existen en C# o Java.
Coroutines son útiles para implementar patrones de productor/consumidor.
Por ejemplo, Python introdujo coroutines en una característica de lenguaje llamada generators, que estaba destinada a simplificar la implementación de iteradores.
También pueden ser útiles para implementar la multitarea cooperativa, donde cada tarea es una corutina que cede a un programador/reactor.
No puedo comentar sobre los generadores de Python, pero he usado una construcción de generador antes, y encontré el concepto ingenioso con grandes problemas de juguete, pero muy difícil de usar en la codificación real. –
Los generadores son muy útiles y ampliamente utilizados en Python de hoy. Pueden producir un código mucho más simple y legible que el equivalente escrito con un objeto, poniendo información de estado en los miembros. Pero no son co-rutinas completas y tienen sus limitaciones en comparación. – bobince
Algunas buenas respuestas que describen qué corutinas son.
Pero para un caso de uso real. Toma un servidor web. Tiene múltiples conexiones simultáneas, y quiere programar la lectura y escritura de todas ellas.
Esto se puede implementar utilizando coroutines. Cada conexión es una corutina que lee/escribe una pequeña cantidad de datos, luego "cede" el control al programador, que pasa a la siguiente corutina (que hace lo mismo) mientras recorremos todas las conexiones disponibles.
No sé por qué esto languideció sin un +1 por tanto tiempo. Un servidor web impulsado por Coroutine, presumiendo que las rutinas se diseñaron correctamente para el cálculo por partes, sería muy útil para un servidor web con mucho peso cuando se trata de rendimiento y sería mucho más fácil de entender que una máquina administrada por una máquina de estado. –
teniendo en cuenta que el sistema operativo puede decirle qué conexiones necesitan su atención, esto parece un enfoque ineficiente. – xaxxon
Muchos de ellos, por ejemplo:
grep TODO *.c *.h | wc -l
La tubería de arriba es exactamente un corrutina: grep
el comando genera una secuencia de líneas que van a un buffer, el comando wc
"se los come"; si el buffer se llena, el grep
"bloquea" hasta que el buffer se vacía, y si el buffer está vacío, el comando wc
espera nueva entrada.
Lo que pasa con las coroutines es que a menudo se usan ahora en patrones más restringidos, como los generadores Python mencionados, o como tuberías.
Si desea ver más en ellos, consulte los artículos de Wikipedia, especialmente en coroutines y iterators.
¡Nunca había pensado en eso! ¡Brillante! – geckos
Como un ejemplo más específico en la línea de productor/consumidor, algo tan simple como el humilde programa de informes por lotes podría usar co-rutinas.
El consejo clave para ese ejemplo es tener un trabajo no trivial para consumir datos de entrada (por ejemplo, analizar datos o acumular cargos y pagos en una cuenta), y un trabajo no trivial para producir el resultado. Cuando tenga estas características:
- Es fácil organizar el código del lado de entrada si puede "emitir" unidades de trabajo en varios lugares.
- También es fácil organizar/entender el código del lado de salida si puede "agarrar" la siguiente unidad de trabajo en una estructura de control anidada.
luego las coronas y las colas son buenas técnicas para tener a su disposición.
Coroutines puede ser útil cada vez que un sistema tiene dos o más piezas de código cuya representación más natural sería como una serie secuencial de pasos que implican una gran cantidad de espera.
Por ejemplo, considere un dispositivo que tiene una interfaz de usuario de teclado y LCD y un módem, y necesita usar el módem para llamar e informar periódicamente su estado independientemente de lo que esté haciendo el usuario en el teclado. La mejor manera de escribir la interfaz de usuario puede ser utilizar funciones como "input_numeric_value (& CONV_SPEED_FORMAT, & conveyor_speed);" que volverá cuando un usuario haya ingresado un valor, y la mejor forma de manejar la comunicación puede ser funciones de uso como "wait_for_carrier();" que volverá cuando la unidad se haya conectado o haya determinado que no va a funcionar.
Sin corutinas, el subsistema UI o el subsistema de módem debería implementarse utilizando una máquina de estado. El uso de corrutinas hace posible que ambos subsistemas se escriban con el estilo más natural. Tenga en cuenta que es importante que ninguno de los subsistemas pase mucho tiempo sin poner las cosas en un estado "consistente" y llame a yield(), ni llama a yield() sin poner primero las cosas en un estado "consistente", pero generalmente no es difícil cumplirlas restricciones
Tenga en cuenta que si bien uno podría utilizar la multitarea completa, eso requiere el uso de bloqueos en cualquier lugar en cualquier momento en que se modifique el estado compartido. Como el conmutador de coroutine nunca cambiará cosas excepto en las llamadas yield(), cualquiera de las dos puede alterar libremente el estado compartido siempre que asegure que todo esté en orden antes de la próxima producción y esté preparado para que la otra rutina altere el estado ". durante "el rendimiento().
Sé que esto es casi 5 años desde que se formuló la pregunta, pero me sorprende que nadie mencionó el caso de uso de juegos donde las coroutinas se usan mucho para medir el tiempo de un cálculo.
Para mantener una velocidad de fotogramas constante en un juego, digamos 60 fps, tiene alrededor de 16.6ms para ejecutar el código en cada fotograma. Eso incluye simulación de física, procesamiento de entrada, dibujo/pintura.
Digamos que su método se ejecuta en cada cuadro. Si su método tarda mucho tiempo y termina abarcando varios fotogramas, va a escalonar el resto del cálculo en el bucle del juego, lo que hace que el usuario vea "jank".
Lo que las coroutines le permiten hacer es, de alguna manera, cortar el tiempo de este cálculo para que se ejecute un poco en cada fotograma. Para que eso suceda, corutinas esencialmente permite que el método "ceda" el cálculo a la "persona que llama" (en este caso, el bucle del juego) para que la próxima vez que se llame se reanude desde donde se quedó. .
Gracias, he pasado una hora tratando de obtener esto, pero su ejemplo es el que realmente hizo que haga clic para mí. –
- 1. ¿Qué es una corrutina?
- 2. ¿Qué son los casos de uso de zeromq?
- 3. ¿Cuáles son los casos de uso para __new__ de Python?
- 4. ¿Qué casos de uso para OWL?
- 5. Casos de uso para IdentityHashMap
- 6. Casos de uso para NoSQL
- 7. Casos de uso para utilidades concurrentes Java
- 8. Casos de uso para JCA
- 9. ¿Cuáles son los casos de uso de jsdom
- 10. ¿Qué tipo de casos de uso aseados existen para/cuándo?
- 11. ¿Cuáles son los posibles casos de uso de AOP?
- 12. Casos de uso para implementar anotaciones
- 13. casos de uso DropBoxManager?
- 14. ¿Cuáles son los casos de uso de Node.js vs Twisted?
- 15. ¿Cuáles son los mejores casos de uso para usar Clojure para un nuevo desarrollo?
- 16. Los casos de uso para @WebInitParam
- 17. Diagramas de casos de uso
- 18. Casos de uso para flujos en Scala
- 19. ¿Cuáles son los casos de uso adecuados para el tipo de datos de matriz PostgreSQL?
- 20. Casos de uso para Clojure en proyectos
- 21. ¿Cuáles son algunos ejemplos de casos de uso para literales de símbolos en Scala?
- 22. ¿Cuáles son los casos de uso para probar Scala 2.9 ... generalización de capturas?
- 23. Casos de uso de PipedInputStream y PipedOutputStream
- 24. ¿Cuáles son algunos casos de uso común para usar el Microkernel Akka?
- 25. ¿Cuáles son los casos de uso adecuados para process.nextTick en Node.js?
- 26. ¿Cuáles son los casos de uso para las funciones de cierre/devolución de llamada en JavaScript?
- 27. Casos de uso para transiciones CSS y animaciones CSS
- 28. Buenos casos de uso de comentarios
- 29. Historias de usuarios vs casos de uso
- 30. ¿Cuáles son los buenos casos de uso para las tuplas en C++ 11?
+1 Se trata de "estado" imo. –