El libro "Competitividad y concurrencia en la plataforma .NET. Patrones de diseño efectivos "

imagen Hola habrozhiteli! El libro de Riccardo Terrell proporciona orientación sobre cómo crear programas competitivos y escalables en .NET, destacando los beneficios de un paradigma funcional y brindando las herramientas y principios apropiados para mantener la competencia de manera competitiva y fácil. Como resultado, armado con nuevas habilidades, recibirá el conocimiento necesario para convertirse en un experto en brindar soluciones exitosas de alto rendimiento.

Si está escribiendo código multiproceso en .NET, este libro puede ayudarlo. Si está interesado en utilizar un paradigma funcional para simplificar la programación competitiva y maximizar el rendimiento de la aplicación, este libro será una guía importante para usted. Beneficiará a cualquier desarrollador .NET que quiera escribir aplicaciones competitivas, reactivas y asíncronas que escalen y se adapten automáticamente a los recursos de hardware existentes donde sea que funcionen dichos programas.

Estructura de publicación: hoja de ruta


Los catorce capítulos de este libro están divididos en tres partes. La Parte I presenta los conceptos funcionales de la programación competitiva y describe las habilidades necesarias para comprender los aspectos funcionales de escribir programas multiproceso.

  • El Capítulo 1 describe los conceptos y objetivos básicos de la programación competitiva, así como las razones para usar la programación funcional para escribir aplicaciones de subprocesos múltiples.
  • El Capítulo 2 explora una gama de tecnologías de programación funcional para mejorar el rendimiento de las aplicaciones multiproceso. El propósito de este capítulo es proporcionar al lector los conceptos utilizados en el resto del libro e introducir ideas poderosas que surgen de un paradigma funcional.
  • El Capítulo 3 ofrece una visión general del concepto funcional de inmutabilidad. Explica cómo se usa la inmutabilidad para escribir programas competitivos predecibles y correctos y para implementar estructuras de datos funcionales que son de naturaleza segura para subprocesos.

En la parte II, se examinan en profundidad varios modelos de programación competitiva en un paradigma funcional. Exploraremos temas como la Biblioteca de tareas paralelas (TPL) e implementaremos patrones paralelos como Bifurcar / Unir, dividir y conquistar, y MapReduce. Esta sección también trata el diseño declarativo, las abstracciones de alto nivel en operaciones asincrónicas, la programación de agentes y la semántica de transferencia de mensajes.

  • El Capítulo 4 describe los conceptos básicos del procesamiento paralelo de grandes cantidades de datos, incluidas plantillas como Fork / Join.
  • El Capítulo 5 presenta métodos más sofisticados para el procesamiento paralelo de grandes cantidades de información, como la agregación paralela, la reducción de datos y la implementación de una plantilla MapReduce paralela.
  • El Capítulo 6 proporciona información detallada sobre los métodos funcionales para procesar flujos de eventos (datos) en tiempo real utilizando los operadores funcionales de alto orden en .NET Reactive Extensions para formar combinadores de eventos asíncronos. Los métodos estudiados se utilizarán luego para implementar una plantilla reactiva competitiva editor-suscriptor.
  • El Capítulo 7 proporciona una explicación del modelo de programación basado en tareas aplicado a la programación funcional para implementar operaciones competitivas utilizando la plantilla Monadic. Luego, este método se utiliza para construir una tubería competitiva basada en un paradigma de programación funcional.
  • El Capítulo 8 está dedicado a la implementación de computación paralela ilimitada utilizando el modelo de programación asíncrono C #. Este capítulo también trata los métodos de manejo de errores y los métodos para construir operaciones asincrónicas.
  • El Capítulo 9 describe el flujo de trabajo asíncrono en F #. Muestra cómo una evaluación diferida y explícita en este modelo permite una mayor semántica compositiva. Luego, aprenderemos cómo implementar expresiones computacionales personalizadas para elevar el nivel de abstracción a la programación declarativa.
  • El Capítulo 10 muestra cómo, en base al conocimiento adquirido en capítulos anteriores, los combinadores y las plantillas, como Functor, Monad y Applicative, se pueden implementar para componer y ejecutar varias operaciones asincrónicas y manejar errores sin efectos secundarios.
  • El Capítulo 11 analiza la programación reactiva utilizando un modelo de mensajería de software. Revela el concepto de aislamiento natural como una tecnología que complementa la inmutabilidad y permite la creación de programas competitivos. Este capítulo se centra en la clase MailboxProcessor utilizada en F # para distribuir el trabajo paralelo utilizando la programación del agente y un enfoque sin recursos.
  • El Capítulo 12 describe la programación del agente utilizando la biblioteca TPL Dataflow de .NET con ejemplos en C #. Muestra cómo implementar agentes sin estado y con estado en C #, así como cómo realizar varios cálculos en paralelo que intercambian datos entre sí, utilizando (enviando) mensajes al estilo de una canalización.

La Parte III muestra cómo poner en práctica todos los métodos funcionales de programación competitiva estudiados en capítulos anteriores.

  • El Capítulo 13 presenta un conjunto de recetas útiles para resolver problemas competitivos complejos, tomados de la práctica real. Estas recetas usan todos los patrones funcionales descritos en este libro.
  • El Capítulo 14 describe una aplicación completa desarrollada e implementada utilizando plantillas y métodos competitivos funcionales estudiados en este libro. Creará una aplicación de servidor altamente escalable y receptiva y un programa de cliente receptivo. El libro contiene dos versiones: una para iOS (iPad), creada con Xamarin Visual Studio, y la segunda, creada con Windows Presentation Foundation (WPF). Para garantizar la máxima escalabilidad en la aplicación del servidor, se utiliza una combinación de varios modelos de programación, como asíncrono, agente y reactivo.

El libro también contiene tres aplicaciones.

  • El Apéndice A describe brevemente los conceptos básicos de la programación funcional, así como presenta la teoría básica de los métodos funcionales utilizados en este libro.
  • El Apéndice B revela los conceptos básicos del lenguaje F #. Esta es una revisión básica de F #, que le permitirá familiarizarse con este idioma y sentirse cómodo mientras lee un libro.
  • El Apéndice B muestra varios métodos que simplifican la interacción entre un flujo de trabajo asíncrono en F # y una tarea .NET en C #.

Extracto 11.6 F # MailboxProcessor: 10,000 agentes para Game of Life


En comparación con los subprocesos, MailboxProcessor en combinación con flujos de trabajo asincrónicos es una unidad de computación simple (primitiva). Los agentes pueden aparecer y ser destruidos a un costo mínimo. Puede distribuir el trabajo entre varios objetos de MailboxProcessor de la misma manera que puede usar hilos, sin la sobrecarga adicional asociada con la creación de un nuevo hilo. Gracias a esto, es muy posible crear aplicaciones que consisten en cientos de miles de agentes que trabajan en paralelo con una carga mínima de recursos informáticos.

En esta sección, utilizaremos varias instancias de MailboxProcessor para implementar el juego Game of Life (el juego "Life") ( wiki-eng y wiki-eng ). Según Wikipedia, el Juego de la vida, en palabras simples, es un autómata celular. Este es un juego sin jugadores; en otras palabras, cuando un juego comienza con una configuración inicial aleatoria, se ejecuta sin ninguna otra entrada. El juego consiste en un conjunto de celdas que forman una cuadrícula; en cada celda se cumplen varias reglas matemáticas. Las células pueden vivir, morir y multiplicarse. Cada celda interactúa con ocho vecinos (celdas vecinas). Para mover celdas de acuerdo con estas reglas, es necesario calcular constantemente el nuevo estado de la cuadrícula.

Game of Life tiene las siguientes reglas:

  • si una celda tiene solo un vecino o ningún vecino, entonces muere "de la soledad";
  • si cuatro o más vecinos de una célula mueren, entonces muere "debido a la sobrepoblación";
  • si la celda tiene dos o tres vecinos, queda por vivir;
  • Si una celda tiene tres vecinos, entonces se multiplica.

Dependiendo de las condiciones iniciales, las células forman estructuras características a lo largo del juego. Mediante la aplicación repetida de las reglas, se crean las siguientes generaciones de células hasta que las células alcanzan un estado estable (Fig. 11.12).

El listado 11.9 muestra la implementación de la celda GameCell AgentCell, basada en los tipos F # de MailboxProcessor. Cada célula del agente interactúa con las células vecinas a través de mensajes asíncronos, creando así un Juego de la Vida totalmente paralelo. Por brevedad, omití algunas partes del código, ya que no están relacionadas con el tema principal del ejemplo. Encontrará la implementación completa en el código fuente de este libro, publicado en el sitio web del editor.

imagen

imagen

AgentCell describe una celda en la cuadrícula Game of Life. El concepto básico es que cada agente intercambia información con las células vecinas sobre su estado actual a través de mensajes asíncronos. Esta plantilla crea una cadena de comunicaciones paralelas interconectadas que involucra a todas las celdas que envían su estado actualizado al MailboxProcessor updateAgent. Después de recibir estos datos, updateAgent actualiza los gráficos en la interfaz de usuario (Listado 11.10).

imagen

imagen

updateAgent, como su nombre lo indica, actualiza el estado de cada píxel de acuerdo con el valor de celda recibido en el mensaje Actualizar. El agente mantiene el estado de los píxeles y lo usa para crear una nueva imagen cuando todas las celdas pasan a su nuevo estado. UpdateAgent luego actualiza la GUI de WPF usando esta nueva imagen que coincide con la cuadrícula actual de Game of Life:

do! Async.SwitchToContext ctx image.Source <- createImage pixels do! Async.SwitchToThreadPool() 

Es importante tener en cuenta que updateAgent utiliza el contexto de sincronización actual para actualizar correctamente el controlador WPF. El hilo actual se cambia al hilo de la interfaz de usuario utilizando la función Async.SwitchToContext (descrita en el Capítulo 9).

El último código para ejecutar Game of Life genera una cuadrícula que sirve como un patio de recreo para las celdas, y luego el temporizador notifica a las celdas sobre la necesidad de realizar una actualización (Listado 11.11). En este ejemplo, la cuadrícula es un cuadrado de 100 × 100 celdas, un total de 10,000 celdas (objetos MailboxProcessor), que se calculan en paralelo con un temporizador cada 50 ms, como se muestra en la Fig. 11.13. Diez mil objetos de MailboxProcessor interactúan y actualizan la interfaz de usuario 20 veces por segundo (el código al que debe prestar atención se muestra en negrita).

imagen

imagen

Las notificaciones a todas las células (agentes) se envían en paralelo usando PLINQ. Las celdas son secuencias F # que se consideran .NET IEnumerable, lo que hace que LINQ / PLINQ sea fácil de integrar.

imagen

Cuando se ejecuta el código, el programa genera 10,000 objetos F # de tipo MailboxProcessor en menos de 1 ms, mientras que los agentes ocupan menos de 25 MB de memoria. Impresionante!

Resumen


  • El modelo de programación basado en agentes proporciona de forma natural la inmutabilidad y el aislamiento al escribir sistemas competitivos, lo que facilita aún más la discusión de sistemas complejos, ya que los agentes están encapsulados dentro de objetos activos.
  • Un manifiesto reactivo define las propiedades para implementar un sistema reactivo que sea flexible, poco acoplado y escalable.
  • El aislamiento natural es importante para escribir código competitivo sin bloquear. En un programa de subprocesos múltiples, el aislamiento resuelve el problema de los estados compartidos al proporcionar a cada subproceso una pieza de datos copiada para realizar cálculos locales. Cuando se usa aislamiento, no hay condición de carrera.
  • Al ser asíncronos, los agentes son simples porque no bloquean los hilos mientras esperan mensajes. Como resultado, puede usar cientos de miles de agentes en una aplicación sin mucho impacto en el tamaño de la memoria.
  • Un objeto MailboxProcessor F # proporciona comunicación bidireccional: un agente puede usar un canal asíncrono para devolver (responder) al objeto llamante el resultado del cálculo.
  • El modelo de programación del agente en F # a través de MailboxProcessor es una herramienta excelente para resolver cuellos de botella en aplicaciones, como el acceso simultáneo a múltiples bases de datos. De hecho, con la ayuda de agentes, puede acelerar significativamente la aplicación, manteniendo la capacidad de respuesta del servidor.
  • Otros lenguajes de programación .NET le permiten utilizar el MailboxProcessor tipo F #, que proporciona métodos que utilizan el conveniente modelo de programación TPL basado en tareas.

»Se puede encontrar más información sobre el libro en el sitio web del editor
» Contenidos
» Extracto

Cupón de 20% de descuento para vendedores ambulantes: concurrencia en .NET

Tras el pago de la versión en papel del libro, se envía una versión electrónica del libro por correo electrónico.

Source: https://habr.com/ru/post/453804/


All Articles