Pregunta

Actualmente estoy aprendiendo programación funcional en mi tiempo libre con Scala, y tengo una pregunta de principiante inactiva.

Puedo ver la elegancia de tener objetos inmutables cuando hago algo como calcular una transformada wavelet de Haar, es decir, cuando los datos que los objetos representan a sí mismos no cambian.

Pero vi un blog donde alguien tenía un pequeño juego como ejemplo al demostrar la inmutabilidad. Si un objeto de criatura recibió daño, no cambió su estado: devolvió un nuevo objeto de criatura con los nuevos puntos de vida y un nuevo '' aggro '' hacia X ''. bandera. Pero si tuviéramos que diseñar algo como un MMORPG, dice World of Warcraft. Un centenar de jugadores en un campo de batalla ... posiblemente miles de ataques y efectos de hechizo de mejora / debilitamiento que los afectan de diferentes maneras. ¿Sigue siendo posible diseñar el sistema con objetos completamente inmutables? A mí me parece que habría un enjambre enorme de nuevas instancias en cada 'tic'. Y para obtener la instancia de objetos actualmente válida, todos los clientes tendrían que pasar constantemente por algún tipo de " gameworld " objeto, o?

¿La programación funcional escala para esto, o es este el caso de la "mejor herramienta para el mejor trabajo, probablemente no sea inmutable aquí?"

¿Fue útil?

Solución

  

Para mí parecería que habría un enjambre descomunal de nuevas instancias cada 'tic'.

De hecho, ese es el caso. Tengo una aplicación Haskell que lee una fuente de datos del mercado (alrededor de cinco millones de mensajes en el transcurso de un día de negociación de seis horas, para los datos que nos interesan) y mantiene el estado actual. por varias cosas, como la oferta más reciente y los precios y cantidades de oferta para los instrumentos, qué tan bien nuestro modelo se ajusta al mercado, etc. etc. Es bastante aterrador simular una ejecución de este programa contra un feed grabado en modo de perfil y ver asigna y GC cerca de 288 TB de memoria (o cerca de 50,000 veces el tamaño de la RAM de mi máquina) en los primeros 500 segundos de su ejecución. (La cifra sería considerablemente mayor sin la creación de perfiles, ya que la creación de perfiles no solo ralentiza la aplicación, sino que también obliga a que todo se ejecute en un solo núcleo).

Pero tenga en cuenta que el recolector de basura en implementaciones de lenguaje puro está optimizado para este tipo de comportamiento. Estoy bastante contento con la velocidad general de mi aplicación, y creo que es bastante exigente, ya que tenemos que analizar varios cientos de mensajes por segundo del feed del mercado, hacer algunos cálculos bastante extensos para construir nuestro modelo y usar eso modelo para generar pedidos para ir al intercambio lo más rápido posible.

Otros consejos

Normalmente, en la programación funcional no tendrá constructores de estilo C ++. Entonces, aunque conceptualmente está creando objetos todo el tiempo, no significa que el compilador tenga que crear un código para asignar un nuevo objeto, ya que no puede afectar el comportamiento del programa. Como los datos son inmutables, el compilador puede ver qué valores acaba de especificar y qué se ha pasado a sus funciones.

Luego, el compilador puede crear código compilado realmente ajustado que solo calcula los campos en los objetos específicos cuando son necesarios. Que tan bien funcione esto depende de la calidad del compilador que use. Sin embargo, el código de programación funcional limpio le dice al compilador mucho más acerca de su código que lo que podría suponer un compilador de C para un programa similar, por lo que un buen compilador puede generar un código mejor de lo que podría esperar.

Entonces, al menos en teoría, no hay razón para preocuparse; Las implementaciones de programación funcional pueden escalarse tan bien como las implementaciones de asignación de pila orientada a objetos. En la práctica, debe comprender la calidad de la implementación de lenguaje con la que está trabajando.

Un MMORPG es ya un ejemplo de inmutabilidad. Dado que el juego se distribuye entre los servidores y los sistemas de los jugadores, no hay absolutamente ningún "mundo de juegos". objeto. Por lo tanto, cualquier objeto que se envíe a través del cable es inmutable, ya que el receptor no lo cambia. En su lugar, un nuevo objeto o mensaje se envía como respuesta, si existe.

Nunca escribí un juego distribuido, así que no sé exactamente cómo se implementan, pero sospecho que las actualizaciones de los objetos se calculan localmente o se envían como datos por cable.

Por ejemplo, estás jugando Command & amp; Conquistar. Su tanque gigantesco está sentado en modo listo protegiendo su base. Tu oponente se acerca con un tanque ligero para explorar tu base. Tu tanque gigantesco dispara y golpea el tanque de tu oponente, causando daño.

Este juego es bastante simple, por lo que sospecho que mucho se calcula localmente siempre que sea posible. Suponga que las computadoras de los dos jugadores están inicialmente sincronizadas en términos de estado del juego. Luego, tu oponente hace clic para mover su tanque ligero a tu base. Se le envía un mensaje (inmutable) por cable. Dado que el algoritmo para mover un tanque es (probablemente) determinístico, su copia de Command & amp; Conquer puede mover el tanque de tu oponente en tu pantalla, actualizando tu estado de juego (podría ser inmutable o mutable). Cuando el tanque ligero llega al alcance de su gigantesco tanque, su tanque se dispara. Se genera un valor aleatorio en el servidor (en este caso, una computadora se elige arbitrariamente como servidor) para determinar si el disparo golpea a su oponente o no. Suponiendo que el tanque fue golpeado y se debe realizar una actualización del tanque de su oponente, solo el diferencial, el hecho de que el nuevo nivel de armadura del tanque ha disminuido al 22%, se envía por cable para sincronizar los juegos de los dos jugadores. Este mensaje es inmutable.

Si el objeto en la computadora de cualquiera de los jugadores que representa el tanque es mutable o inmutable es irrelevante; Se puede implementar de cualquier manera. Cada jugador no cambia directamente el estado del juego de otros jugadores.

Un punto a tener en cuenta sobre la inmutabilidad es que (si se implementa correctamente) hace que la creación de objetos sea relativamente liviana. Si un campo es inmutable, se puede compartir entre instancias.

Es importante tener en cuenta al diseñar un programa funcional que, como usted dice, los objetos inmutables tendrán algo de sobrecarga. También es importante recordar que al tener objetos en su programa MMORPG inmutables, será inherentemente más escalable. Por lo tanto, la inversión inicial en equipo puede ser mayor, pero en el futuro a medida que las cosas se expandan, podrá escalar a su base de jugadores.

Otra cosa importante a tener en cuenta es que, en este momento, las máquinas más potentes tienen 6 núcleos por CPU. Considere una máquina cpu dual con 6 núcleos cada una. Uno de estos 12 núcleos puede estar haciendo la recolección de basura, por lo que la sobrecarga de derribar muchos objetos se puede compensar porque la aplicación es fácilmente escalable a esos otros 11 núcleos.

También recuerda que no todos los objetos (y sus subobjetos) necesitan ser reconstruidos completamente en una copia. Cualquier tipo de referencia que no haya cambiado solo tomará una única asignación de referencia cuando un objeto se copie " ;.

No pienses en la creación de objetos a nivel de cable. Por ejemplo, un tiempo de ejecución optimizado para un lenguaje funcional probablemente podrá " cheat " cuando se trata de reemplazar un objeto y hacer una mutación real de la estructura existente, si sabe que nada hará referencia al original y el nuevo lo reemplaza por completo. Piense en Tail Recursion Optimization, pero se aplica al estado del objeto.

Encontré un blog hoy que trata EXACTAMENTE las preguntas que formulé en esta publicación:

http://prog21.dadgum.com/23.html

Como casi todas las herramientas de programación, los objetos inmutables son poderosos, pero peligrosos en la situación incorrecta. Creo que el ejemplo del juego no es muy bueno o al menos muy artificial.

Eric Lippert tiene algunas publicaciones interesantes sobre el tema de inmutabilidad, y son una lectura bastante interesante.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top