task parallel library - Rendimiento de E/S: Async vs TPL vs Dataflow vs RX
task-parallel-library system.reactive (3)
Cualquier diferencia de rendimiento entre estas opciones sería intrascendente ante "una tonelada de E / S de red y disco".
Una mejor pregunta es "¿con qué opción es más fácil de aprender y de desarrollar?" O "¿qué opción sería la mejor para mantener este código dentro de cinco años?" Y para eso sugeriría primero async
, o Dataflow o Rx si su lógica está mejor representada como una secuencia.
Tengo un fragmento de código C # 5.0 que genera una tonelada de red y E / S de disco. Necesito ejecutar varias copias de este código en paralelo. Cuál de las siguientes tecnologías es probable que me dé el mejor rendimiento:
métodos asíncronos con esperar
usar directamente la tarea de TPL
el nuget de flujo de datos TPL
Extensiones reactivas
No soy muy bueno en estas cosas paralelas, pero si uso una palanca inferior, como por ejemplo Thread, me puede dar un rendimiento mucho mejor también lo consideraría.
Es una pregunta antigua, pero para cualquiera que lea esto ...
Depende. Si intenta saturar el enlace de 1 Gbps con mensajes de 50B, estará vinculado a la CPU incluso con un simple envío sin bloqueo a través de sockets en bruto. Por otro lado, si está satisfecho con el rendimiento de 1 Mbps o si sus mensajes son mayores de 10 KB, cualquiera de estos marcos hará el trabajo.
Para situaciones de poco ancho de banda, recomendaría priorizar por facilidad de uso, es decir, async / await, Dataflow, Rx, TPL en este orden. Tenga en cuenta que la aplicación de alto ancho de banda debe ser prototipada como si fuera de poco ancho de banda y optimizada más adelante.
Para una verdadera aplicación de alto ancho de banda, puedo recomendar Dataflow over Rx, porque Rx no está diseñado para alta concurrencia. Raw TPL es la capa inferior, que garantiza la menor sobrecarga si puede manejar la complejidad. Si puede hacer un uso eficiente de subprocesos dedicados, entonces eso sería aún más rápido. Async / await vs. Dataflow IMO no hace ninguna diferencia de rendimiento. La sobrecarga parece comparable, así que elige una que se ajuste mejor.
Esto es como intentar optimizar la duración de su vuelo transatlántico pidiendo el método más rápido para quitarse el cinturón de seguridad.
Ok, un consejo real, ya que era un poco idiota
Vamos a dar una respuesta útil. Piense en el rendimiento como en "Clases" de actividades, cada una es un orden de magnitud más lenta (¡al menos!):
- Solo accediendo a la CPU, muy poco uso de memoria (es decir, representación de gráficos muy simples a una GPU muy rápida, o cálculo de dígitos de Pi)
- Solo accediendo a cosas de la CPU y de la memoria, nada en el disco (es decir, un juego bien escrito)
- Accediendo al disco
- Accediendo a la red.
Si realiza una de las actividades n. ° 3, no tiene sentido realizar optimizaciones típicas de las actividades n. ° 1 y n. ° 2, como la optimización de las bibliotecas de subprocesos: el impacto del disco los eclipsa por completo. Lo mismo para los trucos de la CPU: si constantemente incurre en falta de memoria caché L2 / L3, no vale la pena ahorrar algunos ciclos de la CPU con el ensamblaje de escritura manual (por lo que las cosas como el desenrollado de bucles son una mala idea en estos días).
Entonces, ¿qué podemos derivar de esto? Hay dos maneras de hacer que su programa sea más rápido, ya sea pasar de # 3 a # 2 (lo cual no es posible, dependiendo de lo que esté haciendo) o haciendo menos E / S. La velocidad de E / S y de la red es el factor limitante de la velocidad en la mayoría de las aplicaciones modernas, y eso es lo que debe intentar optimizar.