process erlang ets

process - Tablas ETS de Erlang versus envío de mensajes: ¿preocupaciones de optimización?



(3)

Parece que tiene muchas cosas que pueden suceder en cualquier momento, y necesita agregar los datos de una manera segura y uniforme. Eche un vistazo al comportamiento del evento genérico . Recomiendo usar esto para crear un servidor de eventos, y hacer que todos estos procesos compartan esta información a través de eventos en su servidor, en ese punto puede elegir registrarlo o almacenarlo en algún lugar (como una tabla ETS). Por otro lado, las tablas ETS no son buenas para datos permanentes como cuántos "widgets" tiene un jugador - considere Mnesia , o un choque excelente solo db como CouchDB . Ambos se replican muy bien en todas las máquinas.

Usted abre una contención de bloqueo: no debe tener bloqueos. Los mensajes se procesan en un orden sincrónico a medida que los recibe cada proceso. De hecho, todo el punto del mensaje que pasa la semántica integrada en el lenguaje es para evitar la concurrencia de estado compartido.
Para resumir, normalmente te comunicas con los mensajes, desde el proceso hasta el proceso. Esto es peliagudo para ti, porque necesitas información de procesos dispersos por todos lados, así que mi recomendación para ti se basa en la idea de concentrar toda la información que es "interesante" fuera de los procesos de origen en una única fuente en tiempo real .

Estoy entrando en un proyecto existente (juego) cuyo componente de servidor está escrito completamente en erlang. A veces, puede ser insoportable obtener un dato de este sistema (me interesa saber cuántos widgets tiene el jugador 56) del proceso que lo posee. Suponiendo que puedo encontrar el proceso que posee los datos, puedo pasar un mensaje a ese proceso y esperar a que devuelva un mensaje, pero esto no se adapta bien a varias máquinas y mata el tiempo de respuesta.

He estado considerando reemplazar muchas de las tareas que existen en este juego con un sistema donde la información a la que acceden frecuentemente múltiples procesos se almacena en una tabla de ets protegidos. El propietario de la tabla no haría más que recibir mensajes de actualización (el jugador acaba de pasar cinco widgets) y actualizar la tabla en consecuencia. Capturaría todas las excepciones y simplemente pasaría al siguiente mensaje de actualización. Cualquier proceso que quisiera saber si el jugador tenía suficientes artilugios para comprar una trampa solo necesitaría echar un vistazo a la mesa. (Sí, entiendo que un mensaje puede estar en el búfer que reduce el número de widgets, pero tengo ese problema bajo control).

Me temo que mi pregunta es menos de una pregunta y más una solicitud de comentarios. Volveré a votar todo lo que sea útil y suficientemente explicado o referenciado.

¿Cuáles son los posibles inconvenientes de tal implementación? Me interesan los detalles de la contención de bloqueos que probablemente veré al tener un escritor-lectores múltiples, qué tipo de problemas tendré distribuyendo esto a través de múltiples máquinas, y especialmente: los comentarios de las personas que lo han hecho esto antes.


En primer lugar, el comportamiento predeterminado de ETS es constante, como puede ver por la documentación: Erlang ETS . Proporciona atomicidad y aislamiento, también múltiples actualizaciones / lecturas si se realiza en la misma función (recuerde que en Erlang una llamada de función es más o menos equivalente a una reducción, la unidad de medida que el planificador de Erlang usa para compartir tiempo entre procesos, entonces una función múltiple ETS la operación podría dividirse en más partes creando una posible condición de carrera).

Si está interesado en la arquitectura de ETS de múltiples nodos, tal vez debería echar un vistazo a mnesia si desea una concurrencia OOTB de nodos múltiples con ETS: Mnesia . (pista: estoy hablando específicamente de tablas ram_copies, métodos add_table_copy y change_config).

Dicho esto, no entiendo el problema con un proceso (posiblemente respaldado por una tabla de ets no nombrada). Explico mejor: el principal problema con su proyecto es la primera suposición básica. Es simple: ¡no tienes un solo proceso de escritura!

Cada vez que un jugador toma un objeto, golpea a un jugador y así sucesivamente, llama a un estado de juego de actualización de función libre de efectos secundarios, por lo que incluso si tiene un solo proceso administrando el estado del juego, también debe decirle a los clientes de otros jugadores ''oye, usted recuerdas ese objeto allí? ¡Solo olvídalo! ''; esta es la razón por la que el principal problema con muchos juegos de varios jugadores es el retraso: el retraso, cuando la creación de redes no es un problema principal, muchas veces se debe al bloqueo de las rutinas de envío / recepción.

Desde este punto de vista, usar directamente una tabla ETS, utilizar una tabla persistente, un diccionario de proceso (¡MALO!), Etc., es lo mismo, porque debe considerar los problemas de sincronización, como en los lenguajes de programación orientados a objetos que utilizan memoria (Java, ¿todos?).

Al final, debe considerar solo UNA preocupación principal en el desarrollo de su aplicación: consistencia. Después de desarrollar una aplicación consistente, solo entonces debe preocuparse por la optimización del rendimiento.

¡Espero eso ayude!

Nota: He hablado sobre algo así como un servidor de MMORPG porque pensé que estabas hablando de algo similar.


Una tabla ETS no resolvería sus problemas en ese sentido. Su código (que quiere obtener o establecer el recuento de widget de jugador) siempre se ejecutará en un proceso y los datos deben copiarse allí.

Ya sea desde un montón de proceso o una tabla ETS hace poca diferencia (dicho esto, la lectura de ETS suele ser más rápida porque está bien optimizada y no realiza ningún otro trabajo que no sea obtener y establecer datos). Especialmente cuando se obtienen datos de un nodo remoto. Para los lectores multple ETS probablemente sea más rápido ya que un proceso manejaría las solicitudes secuencialmente.

Sin embargo, lo que marcaría la diferencia es si los datos están en caché en el nodo local o no. Aquí es donde intervienen los sistemas de bases de datos autorreplicantes, como Mnesia, Riak o CouchDB. De hecho, Mnesia se implementa utilizando tablas ETS.

En cuanto al bloqueo, la última versión de Erlang incluye mejoras en ETS que permiten que varios lectores lean simultáneamente de una tabla más un escritor que escribe. El único elemento bloqueado es la fila en la que se escribe (por lo tanto, mejor rendimiento concurrente que un proceso normal, si espera muchas lecturas simultáneas para un punto de datos).

Sin embargo, tenga en cuenta que toda interacción con tablas ETS no es transaccional. Eso significa que no puede confiar en escribir un valor basado en una lectura previa porque el valor podría haber cambiado mientras tanto. Mnesia maneja eso usando transacciones. Todavía puede usar las funciones dirty_* en Mneisa para exprimir el rendimiento near-ETS de la mayoría de las operaciones, si sabe lo que está haciendo.